Sumant
Sumant

Reputation: 4326

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.

Upvotes: 8

Views: 476

Answers (2)

Aaron McDaid
Aaron McDaid

Reputation: 27133

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

Upvotes: 8

Johannes Schaub - litb
Johannes Schaub - litb

Reputation: 507005

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.

Upvotes: 2

Related Questions