Sign in to follow this  

[SOLVED] - selecting a template using type traits

This topic is 4482 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

[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]

Share this post


Link to post
Share on other sites
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;

}

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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 function
void 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 objects

surface.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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.




Share this post


Link to post
Share on other sites
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 */ );



Share this post


Link to post
Share on other sites
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 :-)

Share this post


Link to post
Share on other sites
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])

Share this post


Link to post
Share on other sites

This topic is 4482 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this