Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is using an integral value parameter pack disallowed after a type parameter pack in C++11?

The question almost does not make sense without an example. So here is what I'm trying to do.

In general C++ allows the following:

template<class T, class U, T t, U u>
void func() {}

func<char, int, 'A', 10>();

But it seems like its natural variadic extension does not work.

template<class...T, T... t>
void func() {}

func<char, int, 'A', 10>(); 

Both clang and g++4.7 reject the above code. The error is shown where the instantiation is done. It appears to me that the two variadic lists should be parsed unambiguously because the first one has types and the other one has integral values only.

If the above is not meant to work, I think the following won't work either.

template <class Ret, class... Args, Ret (*func)(Args...)>
class Foo {};

I think the Foo template is a rather useful thing to have.

like image 806
Sumant Avatar asked Jan 12 '12 03:01

Sumant


People also ask

Which of the following are valid reasons for using Variadic templates in C++?

Variadic templates are class or function templates, that can take any variable(zero or more) number of arguments. In C++, templates can have a fixed number of parameters only that have to be specified at the time of declaration. However, variadic templates help to overcome this issue.

What is a Variadic template C++?

A variadic template is a class or function template that supports an arbitrary number of arguments. This mechanism is especially useful to C++ library developers: You can apply it to both class templates and function templates, and thereby provide a wide range of type-safe and non-trivial functionality and flexibility.

What is a parameter pack C++?

Parameter packs (C++11) A parameter pack can be a type of parameter for templates. Unlike previous parameters, which can only bind to a single argument, a parameter pack can pack multiple parameters into a single parameter by placing an ellipsis to the left of the parameter name.


2 Answers

(Extra: Directly answering your first question, you can also turn template<class...T, T... t> void func() {} into a template-inside-a-template. This doesn't work in g++4.6, but does in clang 3.0, hence it took me a while to find it.)

Put a template inside a template:

template<class ... T>
struct func_types {
   template <T ... t>
   static void func_values() {
       // This next line is just a demonstration, and 
       // would need to be changed for other types:
       printf("%c %d\n", t...);
   }
};

int main() {
    func_types<char, int> :: func_values<'A', 10>();
}

Is a template-inside-a-template acceptable? An alternative is to use tuples with func< tuple<char,int> , make_tuple('A',10) >. I think this is doable, but you might have to roll your own tuple class (it appears that make_tuple isn't a constexpr.

Finally, you might be able to implement your Foo template as follows:

template<typename Ret, typename ...Args>
struct Foo {
        template< Ret (*func)(Args...)>
        struct Bar {
                template<typename T...>
                Bar(T&&... args) {
                        cout << "executing the function gives: "
                           << func(std::forward(args)...) << endl;
                }
        };
};

int main () {
    Foo<size_t, const char*> ::  Bar<strlen> test1("hi");
    Foo<int, const char*, const char*> ::  Bar<strcmp> test2("compare","these");
}

This latter code is on ideone. To demonstrate, I implemented a constructor to forward the args to the function that's code into the template.

like image 127
Aaron McDaid Avatar answered Nov 11 '22 02:11

Aaron McDaid


Because noone has thought it would be worth to have this feature. The design of variadic template was intended to be simple and working. Other potentially advanced and useful features werent included either.

like image 21
Johannes Schaub - litb Avatar answered Nov 11 '22 03:11

Johannes Schaub - litb