Conditional compilation of overloaded functions in template classes - c++

Imagine a class (in VS2010, no variadic templates here sorry)
template <class Arg>
class FunctionWrapper
{
public:
void Invoke(Arg arg){_fn(arg)};
private:
std::function<void(Arg)> _fn;
}
I can then do e.g.
FunctionWrapper <int> foo; foo.Invoke(4);
And this compiles fine. But this does not:
FunctionWrapper <void> foo; foo.Invoke();
Now, I could get around this using template specialization. But I also wondered if there was a way I could get around this another way....
template <class Arg>
class FunctionWrapper
{
public:
void Invoke(void){_fn()}; // } overloaded
void Invoke(Arg arg){_fn(arg)}; // }
private:
std::function<void(Arg)> _fn;
}
i.e. Overload Invoke, and then reply on conditional compilation so that if I instantiate
FunctionWrapper<void>,
the version of Invoke with the argument never gets compiled. I'm sure I read how to do this in Modern C++ design, but I can't remember the details.....

If you were trying to implement a functor this way there would be a number of obvious flaws in the design; I assume, and you seem to make it clear on the comments, that the code is just, well, an example used to state your case.
Here are a couple of solutions to the problem:
template<class T>
struct Trait{
typedef T type;
typedef T mock_type;
};
template<>
struct Trait<void>{
typedef void type;
typedef int mock_type;
};
template <class Arg>
class FunctionWrapper
{
public:
void Invoke(void){_fn();}
void Invoke(typename Trait<Arg>::mock_type arg){_fn(arg);}
boost::function<void(typename Trait<Arg>::type)> _fn;
private:
};
template <class Arg>
class FunctionWrapper2
{
public:
FunctionWrapper2(const boost::function<void(Arg)> arg) : Invoke(arg){}
const boost::function<void(Arg)> Invoke;
};
int main(int argc, _TCHAR* argv[])
{
FunctionWrapper<int> cobi;
cobi._fn = &countOnBits<int>;
cobi.Invoke(5);
FunctionWrapper<void> cobv;
cobv._fn = &func;
cobv.Invoke();
FunctionWrapper2<int> cobi2(&countOnBits<int>);
cobi2.Invoke(5);
FunctionWrapper2<void> cobv2(&func);
cobv2.Invoke();
//[...]
}
Of course I'm not saying that what I wrote is good code, as for the question it is only intended to provide examples of working constructs.
The problem with your attempt is that while the function void Invoke(Arg arg){_fn(arg)}; is actually not being compiled when you instanciate FunctionWrapper (and don't make any attempt at invoking the Invoke function with a parameter), it gets syntactically checked; and of course Invoke(void arg) is not something your compiler is going to accept!
This is my first answer on stackoverflow, I hope I had everything right; if not, please give me some feedback and don't get too upset at me :)

Related

Paradigm regarding template class specialization

I'm currently writing a template class for archiving (or serializing) and unarchiving data into/from a binary format. First off, I'm trying to close on what pattern I'll use. I am mostly inclined to using templates because unarchivers don't have an input type for method overloading. For instance, the following example is OK:
Archiver ar;
int i;
archive(ar, i);
But it's counterpart isn't:
Unarchiver unar;
int i;
i = unarchive(unar);
I would like to avoid using the function's name, such as unarchive_int because it would be troublesome when using templates. Say:
template <class T> class SomeClass
{
public:
void doSomething()
{
// Somewhere
T value = unarchive(unar);
}
};
This would make things messy, and as such I rather really use templates for this, whereas the previous expression would be T value = unarchive<T>(ar);. It also seems silly (arguably) to write a global function if either the first or only parameter are always the archiver and unarchiver objects; a template class seems to be in order:
template <class T> class Archiver
{
public:
void archive(T obj);
};
This works, but the archiving method always copies its input object. This is OK with POD data types, but not so much which classes. The solution seems obvious, and instead use a const reference as in void archive(const T & obj), but now it also seems silly to be passing integers, floats, and other PODs by reference. Although I would be happy with this solution, I tried to go a little further and have the object make the distinction instead. My first approach is std::enable_if, while assuming a copy by default (for all non-class members) and provide a class specialization where the archive method gets its input by reference instead. It doesn't work. Here's the code:
template <class T, class E = void>
class Archiver
{
public:
// By default, obj is passed by copy
void archive(T obj);
};
template <class T>
class Archiver<T, typename std::enable_if<std::is_class<T>::value && !std::is_pod<T>::value>::value>
{
public:
// I would expect this to be used instead if is_class<T> && !is_pod<T>
void archive(const T & obj);
};
The problem is that the second declaration is not visible at all to the compiler, and here's proof:
template <> void Archiver<std::uint8_t>::archive(uint8_t obj);
template <> void Archiver<std::string>::archive(const std::string & obj);
The former compiles fine, but the later gives:
out-of-line declaration of 'archive' does not match any declaration in
'Archiver<std::__1::basic_string<char>, void>'
On the other hand, if I get the std::string instead by copy if compiles just fine. I think I know why this happens, the compiler chooses the first template as it's generic enough for both declarations, but then how do I make it choose the more specialized version?
You want std::enable_if<...>::type, not std::enable_if<...>::value.
Here's a full demo:
#include <type_traits>
#include <cstdint>
#include <string>
template <class T, class E = void>
struct Archiver {
void archive(T obj);
};
template <class T>
struct Archiver<T, typename std::enable_if<std::is_class<T>::value && !std::is_pod<T>::value>::type>
{
void archive(const T & obj);
};
template <> void Archiver<std::uint8_t>::archive(std::uint8_t obj);
template <> void Archiver<std::string>::archive(const std::string & obj);
IIUC, the question boils down to how to define a generic template type that is optimized for calling functions.
For this, you can consider boost::call_traits, in particular, param_type:
template<typename T>
void foo(typename boost::call_traits<T>::param_type t);

function specialization based on if template parameter is shared_ptr

I'm trying to detect if a type is a shared_ptr<T> and if it is, dispatch to a specific function template or override.
Here's a simplified version of what I'm actually attempting:
#include <type_traits>
#include <memory>
#include <cstdio>
template <class T> struct is_shared_ptr : std::false_type {};
template <class T> struct is_shared_ptr<std::shared_ptr<T> > : std::true_type {};
class Foo { };
typedef std::shared_ptr<Foo> SharedFoo;
template<class T> void getValue();
template<class T, typename std::enable_if<is_shared_ptr<T>::value>::type = 0>
void getValue()
{
printf("shared!\n");
}
template<class T, typename std::enable_if<!is_shared_ptr<T>::value>::type = 0>
void getValue()
{
printf("not shared!\n");
}
int main(int, char **)
{
getValue<SharedFoo>();
getValue<Foo>();
return 0;
}
It compiles just fine, but it seems the actual functions were never actually generated because the code doesn't link with the following errors:
/tmp/ccjAKSBE.o: In function `main':
shared_test.cpp:(.text+0x10): undefined reference to `void getValue<std::shared_ptr<Foo>>()'
shared_test.cpp:(.text+0x15): undefined reference to `void getValue<Foo>()'
collect2: error: ld returned 1 exit status
I would think that those would be covered by the two function templates. But they aren't.
Given that, it seems I am seriously misunderstanding something.
So maybe it would help if I explain what I'm /trying/ to do rather than what I'm actually doing.
I have some "magic" code using a bunch of new (to me) C++11 features to bind C++ code to lua (can be seen here: https://github.com/Tomasu/LuaGlue). someone has recently asked for support for binding to classes wrapped in shared_ptr's. which is not something that works at the moment, because it binds at compile time using templates and tuple unwrapping to generate code to call functions on either the C++ or lua side. In the "magic" unwrapping code, I have a bunch of overridden and "specialized" functions that handle various variable types. Some for basic types, one for static objects, and another for pointer to objects. A shared_ptr can't be handled in the same way as either a static or pointer object, so I need to add some extra handling just for them.
For example:
template<typename T>
T getValue(LuaGlue &, lua_State *, unsigned int);
template<>
int getValue<int>(LuaGlue &, lua_State *state, unsigned int idx)
{
return luaL_checkint(state, idx);
}
template<class T>
T getValue(LuaGlue &g, lua_State *state, unsigned int idx)
{
return getValue_<T>(g, state, idx, std::is_pointer<T>());
}
That's the actual code (notice the hairy template/override via function argument :-x).
I had thought it'd be as simple as adding another addValue function, along the lines of the code in my earlier example, via enable_if.
Any reason not to simply use partial specialization?
#include <type_traits>
#include <memory>
#include <cstdio>
class Foo { };
typedef std::shared_ptr<Foo> SharedFoo;
template <class T>
struct getValue {
getValue() {
printf("not shared!\n");
}
};
template <class T>
struct getValue<std::shared_ptr<T> > {
getValue() {
printf("shared!\n");
}
};
int main(int, char **)
{
getValue<SharedFoo>();
getValue<Foo>();
return 0;
}
Your program declares template<class T> void getValue() but doesn't define it. template <typename, typename> void getValue() is a different function. The compiler is picking template<class T> void getValue() as a better match with your invocations, which of course fails at link time as there is no definition of that function.
I prefer the simplicity of tag dispatch when it's applicable (live at Coliru):
template<class T>
void getValue(std::true_type)
{
printf("shared!\n");
}
template<class T>
void getValue(std::false_type)
{
printf("not shared!\n");
}
template<class T>
void getValue() {
return getValue<T>(is_shared_ptr<T>{});
}
Here is another solution which is basically a fix for the OP rather than alternatives (using a class and its constructor as in zennehoy's post or tag dispatch as in Casey's).
// Do not provide this declaration:
// template<class T> void getValue();
template<class T>
typename std::enable_if<is_shared_ptr<T>::value>::type
getValue()
{
printf("shared!\n");
}
template<class T>
typename std::enable_if<!is_shared_ptr<T>::value>::type
getValue()
{
printf("not shared!\n");
}
I must say that, as Casey has put it, I also "prefer the simplicity of tag dispatch". Hence, I would go for his solution.
I also found zennehoy's idea interesting but, unfortunately, it doesn't allow your function to return something. (I believe a workaround is possible but it adds complexity.) With the solution here you just need to provide the return type as the 2nd parameter of std::enable_if.

partial template specialization

I have a scenario in which there is a template class
template<typename X, typename Y>
class Foo
{
typedef Y::NestedType Bar;
int A (Bar thing);
void B();
int C(X that);
// other stuff
};
and then I would like the A() method to have a different behavior when X is a given type (but B and C can stay the same, and the actual code actually has about 10 other methods, a few of which are quite lengthy and subject to frequent tweaking.. so I would rather avoid making a full-class specialization and copy&paste the full class implementation)
I went on and wrote:
template<typename T>
int Foo<MyType, T>::A(Bar thing);
but my compiler (clang 163.7.1) refused to even consider this as a template specialization of any sort.
Is there some syntax error hidden in the way I wrote the code, or is this coding style invalid C++? Unfortunately, even if other compilers do support the idiom, my company is stuck with clang.
Thanks for any help on this.
Use overloading
template<typename X, typename Y>
class Foo
{
// allows to wrap up the arguments
template<typename, typename>
struct Types { };
typedef Y::NestedType Bar;
int A (Bar thing) {
return AImpl(thing, Types<X, Y>());
}
void B();
int C(X that);
// other stuff
private:
template<typename X1, typename Y1>
int AImpl(Bar thing, Types<X1, Y1>) {
/* generic */
}
template<typename Y1>
int AImpl(Bar thing, Types<SpecificType, Y1>) {
/* special */
}
};
You cannot partially specialize a member of a class template. What you wrote would be the definition of a member function A of a partial specialization of the class template itself.

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.

Template Return Types / Cast as function of Template

I'm working with some generated classes with broken polymorphism. For every generated class T, there are a handful of T_type_info, T_writer, T_reader classes which are only related to T conceptually.
What I'm trying to do is something like this:
template <class T> class Wrapper
{
public:
template <class W> W topic_cast(BrokenBaseClassWriter* p);
// other operations with the same problem ...
};
template <> class Wrapper<MyTopic>
{
public:
template <> MyTopicWriter* topic_cast(BrokenBaseClassWriter* p) { ... }
};
So that I can do things like:
void Write(const Wrapper<T>& topic)
{
BrokenBaseClassWriter p = not_important;
topic.topic_cast(p)->do_stuff();
}
My T classes are generated from an IDL and are concepts that exist in application space. They don't derive from anything. In my example above, W is not really an independent parameter, it's "Something Not T that depends on T". I'm trying to keep all knowledge of T in the app, and all knowledge of T' (without knowing about T) in the backend.
The compiler however says my topic_cast function is not a template function - I think because the template occurs in the return type and it wouldn't be distinguishable from any other instantiations. I know that that (templates differ only by return type) is not legal. Only in my case it really would be unique because W is not an independent parameter. But arguing with the compiler is seldom helpful.
Can I do this, or is there another way to do this "cast as function of template type"?
Could this not be achieved with a traits system?
template <typename T> struct my_traits
{
};
template <> struct my_traits<MyClass>
{
typedef MyWriter writer_type;
};
template <typename T> struct Wrapper
{
typename my_traits<T>::writer_type topic_cast();
};
This can't work:
topic.topic_cast(p)->do_stuff();
Because the compiler can not deduce the return type.
So you have to explicitly tell the compiler what return type you want:
topic.topic_cast<MyType>(p)->do_stuff();
The implementation you provide is for a specific type.
So when you use that specific type that code will be produced:
topic.topic_cast<MyTopicWriter>(p)->do_stuff(); // Use the explicit specialization
This compiles with gcc:
class BrokenBaseClassWriter;
class MyTopic;
class MyTopicWriter;
template <class T> class Wrapper
{
public:
template <class W> W *topic_cast(BrokenBaseClassWriter* p);
// other operations with the same problem ...
};
template <> template<>
MyTopicWriter *Wrapper<MyTopic>::topic_cast<MyTopicWriter>(BrokenBaseClassWriter* p)
{
return 0;
}
int main(int argc, int argv)
{
BrokenBaseClassWriter* p = NULL;
Wrapper<MyTopic> caster;
MyTopicWriter *casted = caster.topic_cast<MyTopicWriter>(p);
}
Of course, it still exposes MyTopicWriter in your main code...