|
| En interval klasse Fra : Ken Frøslev |
Dato : 12-07-02 08:34 |
|
Hej,
Jeg har forsøgt at lave en "interval" klasse, som begrænser en type til et
bestemt interval [min;max]. Problemet er at intervallet bestemmes når der
oprettes et nyt object, men jeg vil gerne have intervallet tilknyttet typen.
Er der nogen der har et godt forslag?
template<typename T>
class value_control {
public:
value_control(T v, T min, T max) : max_(max), min_(min) { value_ =
norm(v);}
operator T() {return value_;}
private:
T value_;
const T max_;
const T min_;
T norm(T& v) {
if (v > max_)
v = max_;
if(v < min_)
v = min_;
return v;
}
};
Mvh Ken
| |
Mogens Hansen (12-07-2002)
| Kommentar Fra : Mogens Hansen |
Dato : 12-07-02 11:03 |
|
"Ken Frøslev" <Ken@Froslev.dk> wrote
[snip]
> Er der nogen der har et godt forslag?
Såfremt T er en helttals type (eller en enum) kan man skrive:
template <typename T, T min, T max>
class value_control
{
public:
value_control(const T& value) :
value_(norm(value)) {}
operator T() const
{ return value_; }
private:
static T norm(const T& value)
{
if(value > max) return max;
if(value < min) return min;
return value;
}
private:
T value_;
};
int main()
{
value_control<int, 1, 7> i_1_7(1);
}
Bemærk at funktionen "norm" er static, og måske er kandidat til at blive
lagt i en selvstændig hjælpeklasse/hjælpefunktion, som så kunne gives med
som template argument.
Det kunne dels give lidt større fleksibilitet i udvalget af typer (f.eks.
"float" og "std::string") og dels give større fleksibilitet med hensyn til
hvad der skal ske når værdien kommer uden for det tilladte interval (f.eks.
trunkere, smide en exception, wrappe rundt)
Venlig hilsen
Mogens Hansen
| |
Ken Frøslev (12-07-2002)
| Kommentar Fra : Ken Frøslev |
Dato : 12-07-02 15:57 |
|
Hej igen,
Men at factory pattern kan man lave noget der luget lidt af fisk.Men jeg vil
stadigvæk gerne hører hvis der er nogen der har en bedre ide til hvordan man
kan lave en egentlig type.
Mvh Ken
Program:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
template<class T> class creator;
template<typename T>
class value_control {
public:
operator T() {return value_;}
operator=(const value_control& other) {
min_ = other.min_;
max_ = other.max_;
value_ = other.value;
}
T& operator=(const T& v) {
value_ = norm(v);
//return *this;
}
private:
friend creator<T>;
value_control(T v, T min, T max)
: min_(min), max_(max) { value_ = norm(v); }
private:
T value_;
T max_;
T min_;
T norm(T& v) {
if (v > max_)
v = max_;
if(v < min_)
v = min_;
return v;
}
};
template<typename T>
class creator
{
public:
creator(T min, T max) : min_(min), max_(max) {}
value_control<T> Create(T value = T()) {
return value_control<T>(value, min_, max_);
}
private:
T min_;
T max_;
};
int main(int argc, char* argv[])
{
creator<int> c(1, 5);
value_control<int> vc1 = c.Create(2);
value_control<int> vc2 = c.Create(8);
value_control<int> vc3 = c.Create();
cout << "vc1: " << vc1 << endl;
cout << "vc2: " << vc2 << endl;
cout << "vc3: " << vc3 << endl;
vc3 = vc1 + 5;
vc2 = vc2 * 2;
cout << endl;
cout << "vc1: " << vc1 << endl;
cout << "vc2: " << vc2 << endl;
cout << "vc3: " << vc3 << endl;
creator<string> cre("a", "z");
value_control<string> vc_1_str = cre.Create();
cout << static_cast<string>(vc_1_str) << endl;
value_control<string> vc_2_str = cre.Create("b");
cout << static_cast<string>(vc_2_str) << endl;
char ch;
cin >> ch;
return 0;
}
| |
Mogens Hansen (12-07-2002)
| Kommentar Fra : Mogens Hansen |
Dato : 12-07-02 19:18 |
|
"Ken Frøslev" <Ken@Froslev.dk> wrote
> Men at factory pattern kan man lave noget der luget lidt af fisk.Men jeg
vil
> stadigvæk gerne hører hvis der er nogen der har en bedre ide til hvordan
man
> kan lave en egentlig type.
Det væsentlige problem ved min tidligere løsning, var vel at den kun virkede
for heltal og enum's.
Hvis det skal være en egentlig type (så integer i området 1-7 er en anden
type end integer i området 2-8), så skal måden at specificere grænserne på
formodentlig indgå i type beskrivelsen (som template parametre).
Man kan bruge en peger til en funktion til det formål:
(selvom der indgår pointere til funktioner, kan det hele inlines)
<code>
#include <string>
using namespace std;
template <typename T, T (*Norm)(const T& value)>
class value_control
{
public:
value_control(const T& value) :
value_((*Norm)(value)) {}
operator T()
{ return value_; }
private:
T value_;
};
template <typename T>
inline T range_normalize(const T& value, const T& min, const T& max)
{
if(value > max) return max;
if(min > value) return min;
return value;
}
inline int norm_int_1_7(const int& value)
{
return range_normalize(value, 1, 7);
}
inline string norm_string_a_k(const string& value)
{
static const string min("a");
static const string max("k");
return range_normalize(value, min, max);
}
inline double norm_angle(const double& angle)
{
double result = angle;
while(result > 360) result -= 360;
return result;
}
int main()
{
typedef value_control<int, norm_int_1_7> int_1_7;
int_1_7 i(8);
typedef value_control<string, norm_string_a_k> string_a_k;
string_a_k s1("in range!");
string_a_k s2("out of range!");
typedef value_control<double, norm_angle> angle;
angle a(100.0);
while(a > 25) {
a = a + 25;
}
}
</code>
Andre bud og kommentarer er naturligvis velkomne.
Venlig hilsen
Mogens Hansen
| |
|
|