3

I am starting with variadic templates in C++11 and I wonder if its possible to create a struct / class method that gets its name from a template parameter

Something like:

MySmartTemplate<"foo", int, "bar", double> MyStruct;

// which should result in:
struct MyStruct
{
   void foo(int val){...}
   void bar(double val){...}
};

where the template parameters possibly come pairwise as <name> + <type>

Thanks

x y
  • 911
  • 9
  • 27

2 Answers2

2

This is not possible with templates at all. A template in c++ is parametrized by a list of one or more template parameters. Each of them may be either:

  • a non-type template parameter;
  • a type template parameter;
  • a template template parameter.

Now, to be able to (theoretically) construct something like void foo(int val){...}, you need to pass the name of "foo" and it's parameter type into our imaginary template. While passing the type of val is not a problem, passing "foo"s name is impossible. The only non-type template parameters that you can use are:

  • std::nullptr_t;
  • integral type;
  • lvalue reference type (to object or to function);
  • pointer type (to object or to function);
  • pointer to member type (to member object or to member function);
  • enumeration type.

You should also note that the non-type template parameters of reference and pointer types have a few exceptions, namely they can not refer to or be an address of a string literal (related: this question). Considering the above, there is no way to pass a string literal to a template, and thus it is impossible to achieve what you want with templates.

On a side note, while variadic templates are a nice addition to the language, they have a few limitations, namely you can only perform the expansion of the parameter pack, but you can't address individual parameters in the pack.

So, to conclude, no, what you want is not possible with templates.

Community
  • 1
  • 1
SingerOfTheFall
  • 29,228
  • 8
  • 68
  • 105
  • ...ok, that is not so good. What if the function "name" would be replaced by an index, like tuples< ... > get(i)? – x y Oct 13 '15 at 10:23
  • @xy, well you can store function pointers in a map and get them out of there by index which is passed as a template parameter, but I can't see why would you need to use a template for that at all. – SingerOfTheFall Oct 13 '15 at 10:28
  • Beyond adding /removin some template parameter - it's about ordering. Suppose the order of template parameter is important, so that the one that comes first in the parameter pack does something different, than the other ones... – x y Oct 13 '15 at 10:47
1

Unfortunately no. Templates mechanism allows you only to have fun with type genericness, i.e. create functions/objects that can work with multiple types, or have slightly different implementation for different input types, or make a return type depend on a template argument, etc. In general, template meta-programming introduces so called static polymorphism. It's a compiler stage's feature (check out compilation stages) which means it's done after all names are fixed (function foo() will be always called foo even if compiler decides to use it with an int argument).

What you are trying to achieve is to get into proprocessor stage, in which a source code can be modified using preprocessor directives. This is the moment when you can play around with macros. For your example you could use something like this:

#include <iostream>

using namespace std;

#define MySmartTemplate(StructName, Func1Name, Func1ArgType, Func2Name, Func2ArgType) \
struct StructName \
{ \
    void Func1Name(Func1ArgType val) { cout << "func1" << endl; } \
    void Func2Name(Func2ArgType val) { cout << "func2" << endl; } \
};

MySmartTemplate(MyStruct, foo, int, bar, double);

int main()
{
    MyStruct myStruct;
    myStruct.foo(1);
    myStruct.bar(1);
}

Live demo


Certainly, you can use macros with templates which would give you even more flexibility.

psliwa
  • 1,094
  • 5
  • 9
  • "Templates mechanism allows you only to have fun with type genericness, i.e. create functions/objects that can work with multiple **types**". So if I would pass different _function pointers_ as template parameters, it would - kindof - simulate my idea..., I will look at that, but thanks for clarification... – x y Oct 13 '15 at 10:36