[SOLVED] - selecting a template using type traits

Started by
7 comments, last by Verg 18 years, 7 months ago
[EDITED...] I've run into a problem that could be fixed if only this would work: (example)

template<bool on = true>
class test{

public:

    void do_test()
    {
        #if (on)
        cout << "Test is: ON"
        #else
        cout << "Test is: OFF"
        #endif
        << endl;
    }
};

int main
{
   test<> t;
   test<false> t1;

   t.do_test();
   t1.do_test();

   return 0;
}
The behavior requested should be obvious.... but... it doesn't work. The preprocessor doesn't pick up the compile-time constant. The conditional compilation is mandatory, because the passed-in parameter type will refuse to compile for certain types... (the line it chokes on needs to be conditionally compiled out) Is there a way to do this? (The application in question is a templated member function that deduces a type based on the parameter) Thanks for any ideas. Chad [Edited by - Verg on September 7, 2005 10:45:34 PM]
my_life:          nop          jmp my_life
[ Keep track of your TDD cycle using "The Death Star" ] [ Verge Video Editor Support Forums ] [ Principles of Verg-o-nomics ] [ "t00t-orials" ]
Advertisement
You can't put preprocessor behaviour with the template parameter. You can introduce template specializations for on being true or false, or you can just do:
    void do_test()    {        if (on)          cout << "Test is: ON";        else          cout << "Test is: OFF";        cout << endl;    }
Quote:Original post by SiCrane
You can't put preprocessor behaviour with the template parameter. You can introduce template specializations for on being true or false, or you can just do:
    void do_test()    {        if (on)          cout << "Test is: ON";        else          cout << "Test is: OFF";        cout << endl;    }

Note that this if will be optimized out during comilation as on is a constant and hence known at compiletime.

In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.

Yeah, I've already looked at template specializations... and it's not really an option... because I'd have to specialize maybe a hundred different types.

The real problem looks more like this:

// inside class "Surface"template<ValueType>   // member template functionvoid getAttribute(ValueType &variable, const char *name){// the attribute string is stored in a map, keyed by "name"...// after retrieving it, the string is parsed using boost::spirit...// the string "may" have a form like this:// [00abf560]/2 + 50// The bracketed [] number is a pointer to a ValueType object;// in other words, the parser evaluates what is pointed at by "00abf560" // as a ValueType object.// Now! If the ValueType is "long", for instance, then the string// looks like this:// (100)/2 + 50//ValueType temp;parser = pointer_parser[assign_ptr(temp,ptr)] | real_p[assign_a(temp)];}///// here's how to instantiate the member function objectssurface.getAttribute(_width, "width");surface.getAttribute(_height, "height");surface.getAttribute(_point, "position"); // chokes here...// The reason it chokes was as explained... I don't need a "real_p" parser// when parsing a "Point" attribute string, but I *do* need it for values (like// width, and height) which can be converted from real numbers.// in other words, for all types which can be assigned a "double"


(this is just a portion of the code)

The problem happens on that line... "parser = real_p[assign_a(temp)];"

Without explaining how Spirit works... when you assign a "rule" (or a parser),
spirit creates actor objects... like the assign actor. These "actors" overload
their () operator, and define an operation something like:

RefType &r = ValType &v

Problem is... what happens when you call "assign_a(temp)"... with the type of "temp" == "class Point" and you try to assign the result of "real_p" to it?

Compiler chokes.

Point = double

(doesn't work).

------

Now... what I'm TRYING to do is conditionally compile a parser string that uses "real_p" for all types that can be assigned a "double"... and for all types that can't do this:

type = double

the "real_p" parser isn't put into the parser string.

....

See what I'm getting at?

Anywho... big problem...

Is there a reasonable solution that's not too wacky?

Thanks again.


C
my_life:          nop          jmp my_life
[ Keep track of your TDD cycle using "The Death Star" ] [ Verge Video Editor Support Forums ] [ Principles of Verg-o-nomics ] [ "t00t-orials" ]
Define a traits class such that a static const bool in the class evaluates to true for things that can be assigned by double, and false otherwise. Then do a template select based on the result of the traits class, that requires only two specializations for the function, and only specializes the traits class for things that are assignable by double.
Quote:Original post by SiCrane
Define a traits class such that a static const bool in the class evaluates to true for things that can be assigned by double, and false otherwise. Then do a template select based on the result of the traits class, that requires only two specializations for the function, and only specializes the traits class for things that are assignable by double.


Thanks. I'm not quite sure if I know how to do that, but I'll try it.

Thanks again.




my_life:          nop          jmp my_life
[ Keep track of your TDD cycle using "The Death Star" ] [ Verge Video Editor Support Forums ] [ Principles of Verg-o-nomics ] [ "t00t-orials" ]
SiCrane:

Something like this??

template<typename ValueType,         bool convertible = TypeTraits<ValueType>::numericallyConvertible        >void getAttribute(ValueType &v, const char *name);// specializations?template<>void Surface::getAttribute<false>( /* whatever in here */ );template<>void Surface::getAttribute<true>( /* whatever in here */ );


my_life:          nop          jmp my_life
[ Keep track of your TDD cycle using "The Death Star" ] [ Verge Video Editor Support Forums ] [ Principles of Verg-o-nomics ] [ "t00t-orials" ]
Well... that last one didn't work...

Here's what I tried:

class Surface{public:// ...template<typename ValueType, typename Loki::TypeTraits<ValueType>::isStdArith >void getAttribute(ValueType &v, const char *name){//...}};


I probably don't understand the application of the type traits class. Is it applied where you instantiate the functions? If so, then it is completely useless.

e.g.

surface.getAttribute(_width, "width"); // here, I KNOW the type of "_width"surface.getAttribute(_pt, "pos"); // I also know that "_pt" is_a "Point"// if that's the case, why don't I just call a different template by hand for ]// each type?// because that sucks, that's why :-)

my_life:          nop          jmp my_life
[ Keep track of your TDD cycle using "The Death Star" ] [ Verge Video Editor Support Forums ] [ Principles of Verg-o-nomics ] [ "t00t-orials" ]
Solved. Here's the solution:

class Surface{public:    template<typename ValueType>    void getAttribute(ValueType &v, const char *name)    {        GetAttribute<Loki::TypeTraits<ValueType>::isStdArith> getter;        getter.getAttribute(v,name);    }private:    template<bool numeric = true>    class GetAttribute{    public:            template<typename ValueType>        void getAttribute(ValueType &v, const char *name)        {            // implementation #1 here        }    };    template<>    class GetAttribute<false>{    public:            template<typename ValueType>        void getAttribute(ValueType &v, const char *name)        {            // implementation #2 here        }    };};


Thanks for the help though. Your rating was pushed (someday you may pass 2000 [grin])
my_life:          nop          jmp my_life
[ Keep track of your TDD cycle using "The Death Star" ] [ Verge Video Editor Support Forums ] [ Principles of Verg-o-nomics ] [ "t00t-orials" ]

This topic is closed to new replies.

Advertisement