Conditional Compile using Boost type-traits - c++

I have a template that I would like to conditionally compile depending on the type of the argument. I only care about differentiating between "Plain Old Data" (POD), i.e., integers, etc or classes/structs. I'm using c++ VS2008 on Windows.
template<T>
class foo
{
void bar(T do_something){
#if IS_POD<T>
do something for simple types
#else
do something for classes/structs
#endif
}}
I've been looking at the boost library's and I can see that they appear to have what I want. However, I do not understand what the correct syntax for the #if statement would be.
Any help would be appreciated.
Edit ---
After reading the responses, I see I overlooked something in my definition of the question. Class foo is a templated class that only needs to instance the version of bar that is correct for class type T. I was looking for a solution that can be resolved a compile time. Hope this clears up my problem.

You can do it without enable_if, because all you need is to dispatch depending on type traits. enable_if is used to add/remove template instantiations to/from overload resolution. You may want to use call traits to choose the best method to pass objects to your function. As a rule, objects should be passed by reference, whereas POD is passed by value. call_traits let's you choose between const and non-const references. The code below uses const reference.
#include <boost/type_traits.hpp>
#include <boost/call_traits.hpp>
template <typename T>
class foo {
public:
void bar(typename boost::call_traits<T>::param_type obj) {
do_something(obj, boost::is_pod<T>());
}
private:
void do_something(T obj, const boost::true_type&)
{
// do something for POD
}
void do_something(const T& obj, const boost::false_type&)
{
// do something for classes
}
};

You can't solve this with the preprocessor, since it doesn't know about C++. (It's a dumb text replacement tool.) Use templates to do this.
Assuming IsPod<T>::result returns something alike Boolean<true>/Boolean<false>:
template<T>
class foo
{
void do_something(T obj, Boolean<true> /*is_pod*/)
{
// do something for simple types
}
void do_something(T obj, Boolean<false> /*is_pod*/)
{
// do something for classes/structs
}
void bar(T obj)
{
do_something(obj, IsPod<T>::result());
}
}

Using preprocessor here is not possible. Have a look at Boost Enable If library instead.
Specifically, in your case it would look like (not tested):
void bar (typename enable_if <is_pod <T>, T>::type do_something)
{
// if is POD
}
void bar (typename disable_if <is_pod <T>, T>::type do_something)
{
// if not
}

Related

Detect template parameter type [duplicate]

In my template-ized function, I'm trying to check the type T is of a specific type. How would I do that?
p/s I knew the template specification way but I don't want to do that.
template<class T> int foo(T a) {
// check if T of type, say, String?
}
Thanks!
Instead of checking for the type use specializations. Otherwise, don't use templates.
template<class T> int foo(T a) {
// generic implementation
}
template<> int foo(SpecialType a) {
// will be selected by compiler
}
SpecialType x;
OtherType y;
foo(x); // calls second, specialized version
foo(y); // calls generic version
If you don't care about compile-time, you may use boost::is_same.
bool isString = boost::is_same<T, std::string>::value;
As of C++11, this is now part of the standard library
bool isString = std::is_same<T, std::string>::value
hmm because I had a large portion of
same code until the 'specification'
part.
You can use overloading, but if a large part of the code would work for any type, you might consider extracting the differing part into a separate function and overload that.
template <class T>
void specific(const T&);
void specific(const std::string&);
template <class T>
void something(const T& t)
{
//code that works on all types
specific(t);
//more code that works on all types
}
I suppose you could use the std::type_info returned by the typeid operator
I suspect someone should tell you why it might not be a good idea to avoid using overloading or specialization. Consider:
template<class T> int foo(T a) {
if(isAString<T>()) {
return a.length();
} else {
return a;
}
}
You might think on a first sight that it will work for int too, because it will only try to call length for strings. But that intuition is wrong: The compiler still checks the string branch, even if that branch is not taken at runtime. And it will find you are trying to call a member function on non-classes if T is an int.
That's why you should separate the code if you need different behavior. But better use overloading instead of specialization, since it's easier to get a clue how things work with it.
template<class T> int foo(T a) {
return a;
}
int foo(std::string const& a) {
return a.length();
}
You have also better separated the code for different paths of behavior. It's not all anymore clued together. Notice that with overloading, the parameters may have different type forms and the compiler will still use the correct version if both match equally well, as is the case here: One can be a reference, while the other can not.
You can check using type_traits (available in Boost and TR1) (e.g. is_same or is_convertible) if you really want to avoid specialization.
You can perform static checks on the type that you have received (look at the boost type traits library), but unless you use specialization (or overloads, as #litb correctly points out) at one point or another, you will not be able to provide different specific implementations depending on the argument type.
Unless you have a particular reason (which you could add to the question) not to use the specialization in the interface just do specialize.
template <> int subtract( std::string const & str );
If you are using C++11 or later, std::is_same does exactly what you want:
template <typename T>
constexpr bool IsFloat() { return std::is_same<T, float>::value; }
template <typename T>
void SomeMethodName() {
if (IsFloat<T>()) {
...
}
}
http://en.cppreference.com/w/cpp/types/is_same

Given a T and function name and type, how can I resolve T::function?

Given an Event struct and an object that implements a function with a specific name and prototype, known by the Event struct, I want to return a pointer or bind to that function. Exactly what it returns doesn't matter; it can just as easily be a pointer-to-member-function or a bind.
It's a bit hard to explain, so here's some psuedo-code:
struct Foo {
void onEvent();
};
struct Bar {
void onEvent();
};
struct Event
{
// I'm not sure what would go here
// Needs something that can be used to resolve T::onEvent, without
// knowing what T is until GetEventFunction is called.
typedef std::function<void()> function_type;
};
template<typename T, typename EventType>
EventType::function_type GetEventFunction(T* object)
{
return std::bind(T::(EventType::Something), object);
}
GetEventFunction<Foo, Event>(new Foo); // Returns Foo::onEvent
GetEventFunction<Bar, Event>(new Bar); // Returns Bar::onEvent
Can this behavior be achieved, or is C++ too limited to allow this?
Please read this before answering
I am not looking for reflection. As far as I'm aware, all of the information needed to do what I'm aiming for is available at compile time.
Also, I am not interested in alternate approaches. I know many ways to achieve this behavior with additional code, such as template specializations for each Event type, but I'm looking for a way to achieve this specifically.
Maybe I didn't explain well, but the function name is unique for each Event type. A FooEvent should resolve T::onFooEvent, while a BarEvent should resolve T::onBarEvent.
C++ can operate on types and values, but not on names. That's dealing with text, which is a macro-level thing that happens before C++ proper gets to look at the code. You can't take the type BarEvent and convert it into the function T::onBarEvent, because there is no association between them except for what they happen to be named.
That's why Luc's answer used a specific name: names of functions have to be hard-coded.
Now, you can side-step C++'s rules a bit via the use of a traits template. For example, you can create an event_traits template type that has a member function which takes T and calls a specific function on it. It would look like this:
template<typename event_type>
struct event_traits
{
template<typename T> void Dispatch(T *t) {t->DefaultEventFunction();}
};
The above uses DefaultEventFunction.
If you want each Event to have its own event function, you'll need a specialization for each Event class. And if you want to enforce this rule, simply never define DefaultEventFunction in any of your T objects; the compiler will complain. Change the name into something unlikely to be used, like WhyDidYouNameThisFunctionLikeThisStopIt.
template<>
struct event_traits<FooEvent>
{
template<typename T> void Dispatch(T *t) {t->onFooEvent();}
};
template<>
struct event_traits<BarEvent>
{
template<typename T> void Dispatch(T *t) {t->onBarEvent();}
};
This is where macros can come in handy:
#define REGISTER_EVENT_HANDLER(eventName)\
template<> struct event_traits<eventName>\
{\
template<typename T> void Dispatch(T *t) {t->on ## eventName ();}\
};
Thus, your GetEventFunction would look like this:
template<typename T, typename EventType>
EventType::function_type GetEventFunction(T* object)
{
return std::bind(event_traits<EventType>::Dispatch<T>, object);
}
If you do have the name of the member, then you don't need to know of a type -- assuming that member is not an overloaded member function.
template<typename T>
auto GetEventFunction(T& object)
-> decltype( std::bind(&T::onEvent, std::ref(object)) )
{ return std::bind(&T::onEvent, std::ref(object)); }
// Usage:
Foo f;
auto event = GetEventFunction(f);
Note that this is somewhat contrived, because the onEvent you mentioned doesn't take any arguments. If it did, you'd need more scaffolding. (I'd recommend writing a mem_fn that also accepts an object, unlike std::mem_fn.)

How to pass a method pointer as a template parameter

I am trying to write a code that calls a class method given as template parameter. To simplify, you can suppose the method has a single parameter (of an arbitrary type) and returns void. The goal is to avoid boilerplate in the calling site by not typing the parameter type. Here is a code sample:
template <class Method> class WrapMethod {
public:
template <class Object>
Param* getParam() { return &param_; }
Run(Object* obj) { (object->*method_)(param_); }
private:
typedef typename boost::mpl::at_c<boost::function_types::parameter_types<Method>, 1>::type Param;
Method method_;
Param param_
};
Now, in the calling site, I can use the method without ever writing the type of the parameter.
Foo foo;
WrapMethod<BOOST_TYPEOF(&Foo::Bar)> foo_bar;
foo_bar.GetParam()->FillWithSomething();
foo_bar.Run(foo);
So, this code works, and is almost what I want. The only problem is that I want to get rid of the BOOST_TYPEOF macro call in the calling site. I would like to be able to write something like WrapMethod<Foo::Bar> foo_bar instead of WrapMethod<BOOST_TYPEOF(&Foo::Bar)> foo_bar.
I suspect this is not possible, since there is no way of referring to a method signature other than using the method signature itself (which is a variable for WrapMethod, and something pretty large to type at the calling site) or getting the method pointer and then doing typeof.
Any hints on how to fix these or different approaches on how to avoid typing the parameter type in the calling site are appreciated.
Just to clarify my needs: the solution must not have the typename Param in the calling site. Also, it cannot call FillWithSomething from inside WrapMethod (or similar). Because that method name can change from Param type to Param type, it needs to live in the calling site. The solution I gave satisfies both these constraints, but needs the ugly BOOST_TYPEOF in the calling site (using it inside WrapMethod or other indirection would be fine since that is code my api users won't see as long as it is correct).
Response:
As far as I can say, there is no possible solution. This boil down to the fact that is impossible to write something like WrapMethod<&Foo::Bar>, if the signature of Bar is not known in advance, even though only the cardinality is necessary. More generally, you can't have template parameters that take values (not types) if the type is not fixed. For example, it is impossible to write something like typeof_literal<0>::type which evalutes to int and typeof_literal<&Foo::Bar>::type, which would evaluate to void (Foo*::)(Param) in my example. Notice that neither BOOST_TYPEOF or decltype would help because they need to live in the caling site and can't be buried deeper in the code. The legitimate but invalid syntax below would solve the problem:
template <template<class T> T value> struct typeof_literal {
typedef decltype(T) type;
};
In C++0x, as pointed in the selected response (and in others using BOOST_AUTO), one can use the auto keyword to achieve the same goal in a different way:
template <class T> WrapMethod<T> GetWrapMethod(T) { return WrapMethod<T>(); }
auto foo_bar = GetWrapMethod(&Foo::Bar);
Write it as:
template <typename Object, typename Param, void (Object::*F)(Param)>
class WrapMethod {
public:
Param* getParam() { return &param_; }
void Run(Object* obj) { (obj->*F)(param_); }
private:
Param param_;
};
and
Foo foo;
WrapMethod<Foo, Param, &Foo::Bar> foo_bar;
foo_bar.getParam()->FillWithSomething();
foo_bar.Run(foo);
EDIT: Showing a template function allowing to do the same thing without any special template wrappers:
template <typename Foo, typename Param>
void call(Foo& obj, void (Foo::*f)(Param))
{
Param param;
param.FillWithSomthing();
obj.*f(param);
}
and use it as:
Foo foo;
call(foo, &Foo::Bar);
2nd EDIT: Modifying the template function to take the initialization function as a parameter as well:
template <typename Foo, typename Param>
void call(Foo& obj, void (Foo::*f)(Param), void (Param::*init)())
{
Param param;
param.*init();
obj.*f(param);
}
and use it as:
Foo foo;
call(foo, &Foo::Bar, &Param::FillWithSomething);
If your compiler supports decltype, use decltype:
WrapMethod<decltype(&Foo::Bar)> foo_bar;
EDIT: or, if you really want to save typing and have a C++0x compliant compiler:
template <class T> WrapMethod<T> GetWrapMethod(T) { return WrapMethod<T>(); }
auto foo_bar= GetWrapMethod(&Foo::Bar);
EDIT2: Although, really, if you want it to look pretty you either have to expose users to the intricacies of the C++ language or wrap it yourself in a preprocessor macro:
#define WrapMethodBlah(func) WrapMethod<decltype(func)>
Have you considered using method templates?
template <typename T> void method(T & param)
{
//body
}
Now the compiler is able to implicitly determine parameter type
int i;
bool b;
method(i);
method(b);
Or you can provide type explicitly
method<int>(i);
You can provide specializations for different data types
template <> void method<int>(int param)
{
//body
}
When you are already allowing BOOST_TYEPOF(), consider using BOOST_AUTO() with an object generator function to allow type deduction:
template<class Method> WrapMethod<Method> makeWrapMethod(Method mfp) {
return WrapMethod<Method>(mfp);
}
BOOST_AUTO(foo_bar, makeWrapMethod(&Foo::Bar));
Okay let's have a go at this.
First of all, note that template parameter deduction is available (as noted in a couple of answers) with functions.
So, here is an implementation (sort of):
// WARNING: no virtual destructor, memory leaks, etc...
struct Foo
{
void func(int e) { std::cout << e << std::endl; }
};
template <class Object>
struct Wrapper
{
virtual void Run(Object& o) = 0;
};
template <class Object, class Param>
struct Wrap: Wrapper<Object>
{
typedef void (Object::*member_function)(Param);
Wrap(member_function func, Param param): mFunction(func), mParam(param) {}
member_function mFunction;
Param mParam;
virtual void Run(Object& o) { (o.*mFunction)(mParam); }
};
template <class Object, class Param>
Wrap<Object,Param>* makeWrapper(void (Object::*func)(Param), Param p = Param())
{
return new Wrap<Object,Param>(func, p);
}
int main(int argc, char* argv[])
{
Foo foo;
Wrap<Foo,int>* fooW = makeWrapper(&Foo::func);
fooW->mParam = 1;
fooW->Run(foo);
Wrapper<Foo>* fooW2 = makeWrapper(&Foo::func, 1);
fooW2->Run(foo);
return 0;
}
I think that using a base class is the native C++ way of hiding information by type erasure.

Semi-generic function

I have a bunch of overloaded functions that operate on certain data types such as int, double and strings. Most of these functions perform the same action, where only a specific set of data types are allowed. That means I cannot create a simple generic template function as I lose type safety (and potentially incurring a run-time problem for validation within the function).
Is it possible to create a "semi-generic compile time type safe function"? If so, how? If not, is this something that will come up in C++0x?
An (non-valid) idea;
template <typename T, restrict: int, std::string >
void foo(T bar);
...
foo((int)0); // OK
foo((std::string)"foobar"); // OK
foo((double)0.0); // Compile Error
Note: I realize I could create a class that has overloaded constructors and assignment operators and pass a variable of that class instead to the function.
Use sfinae
template<typename> struct restrict { };
template<> struct restrict<string> { typedef void type; };
template<> struct restrict<int> { typedef void type; };
template <typename T>
typename restrict<T>::type foo(T bar);
That foo will only be able to accept string or int for T. No hard compile time error occurs if you call foo(0.f), but rather if there is another function that accepts the argument, that one is taken instead.
You may create a "private" templatized function that is never exposed to the outside, and call it from your "safe" overloads.
By the way, usually there's the problem with exposing directly the templatized version: if the passed type isn't ok for it, a compilation error will be issued (unless you know your algorithm may expose subtle bugs with some data types).
You could probably work with templates specializations for the "restricted" types you want to allow. For all other types, you don't provide a template specialization so the generic "basic" template would be used. There you could use something like BOOST_STATIC_ASSERT to throw a compile error.
Here some pseudo-code to clarify my idea:
template <typename T>
void foo(T bar) {BOOST_STATIC_ASSERT(FALSE);}
template<> // specialized for double
void foo(double bar) {do_something_useful(bar);};
Perhaps a bit ugly solution, but functors could be an option:
class foo {
void operator()(double); // disable double type
public:
template<typename T>
void operator ()(T bar) {
// do something
}
};
void test() {
foo()(3); // compiles
foo()(2.3); // error
}
Edit: I inversed my solution
class foo {
template<typename T>
void operator ()(T bar, void* dummy) {
// do something
}
public:
// `int` is allowed
void operator ()(int i) {
operator ()(i, 0);
}
};
foo()(2.3); // unfortunately, compiles
foo()(3); // compiles
foo()("hi"); // error
To list an arbitrary selection of types I suppose you could use a typelist. E.g see the last part of my earlier answer.
The usage might be something like:
//TODO: enhance typelist declarations to hide the recursiveness
typedef t_list<std::string, t_list<int> > good_for_foo;
template <class T>
typename boost::enable_if<in_type_list<T, good_for_foo> >::type foo(T t);

How do I check my template class is of a specific classtype?

In my template-ized function, I'm trying to check the type T is of a specific type. How would I do that?
p/s I knew the template specification way but I don't want to do that.
template<class T> int foo(T a) {
// check if T of type, say, String?
}
Thanks!
Instead of checking for the type use specializations. Otherwise, don't use templates.
template<class T> int foo(T a) {
// generic implementation
}
template<> int foo(SpecialType a) {
// will be selected by compiler
}
SpecialType x;
OtherType y;
foo(x); // calls second, specialized version
foo(y); // calls generic version
If you don't care about compile-time, you may use boost::is_same.
bool isString = boost::is_same<T, std::string>::value;
As of C++11, this is now part of the standard library
bool isString = std::is_same<T, std::string>::value
hmm because I had a large portion of
same code until the 'specification'
part.
You can use overloading, but if a large part of the code would work for any type, you might consider extracting the differing part into a separate function and overload that.
template <class T>
void specific(const T&);
void specific(const std::string&);
template <class T>
void something(const T& t)
{
//code that works on all types
specific(t);
//more code that works on all types
}
I suppose you could use the std::type_info returned by the typeid operator
I suspect someone should tell you why it might not be a good idea to avoid using overloading or specialization. Consider:
template<class T> int foo(T a) {
if(isAString<T>()) {
return a.length();
} else {
return a;
}
}
You might think on a first sight that it will work for int too, because it will only try to call length for strings. But that intuition is wrong: The compiler still checks the string branch, even if that branch is not taken at runtime. And it will find you are trying to call a member function on non-classes if T is an int.
That's why you should separate the code if you need different behavior. But better use overloading instead of specialization, since it's easier to get a clue how things work with it.
template<class T> int foo(T a) {
return a;
}
int foo(std::string const& a) {
return a.length();
}
You have also better separated the code for different paths of behavior. It's not all anymore clued together. Notice that with overloading, the parameters may have different type forms and the compiler will still use the correct version if both match equally well, as is the case here: One can be a reference, while the other can not.
You can check using type_traits (available in Boost and TR1) (e.g. is_same or is_convertible) if you really want to avoid specialization.
You can perform static checks on the type that you have received (look at the boost type traits library), but unless you use specialization (or overloads, as #litb correctly points out) at one point or another, you will not be able to provide different specific implementations depending on the argument type.
Unless you have a particular reason (which you could add to the question) not to use the specialization in the interface just do specialize.
template <> int subtract( std::string const & str );
If you are using C++11 or later, std::is_same does exactly what you want:
template <typename T>
constexpr bool IsFloat() { return std::is_same<T, float>::value; }
template <typename T>
void SomeMethodName() {
if (IsFloat<T>()) {
...
}
}
http://en.cppreference.com/w/cpp/types/is_same