Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Universal reference to template template parameter

Is it possible to pass a template template paramater value by universal reference? Consider for example this minimal example for a function (not) working on STL sequences:

#include <iostream>
#include <vector>

template < template<typename,typename> class C, template<typename> class A, typename T >
void func(C<T, A<T>>&& c) {
    // usually I'd std::forward here, but let's just use cout...
    std::cout << c.size() << "\n";
}

int main (int argc, char const* argv[]) {
    func(std::vector<float>(2));
    std::vector<float> lv(3);
    func(lv);
}

It won't compile since the compiler doesn't know how to bind the l-value ("lv") in the second call to func. I'm a bit lost when it comes to the deduction rules for the type of C. Can anyone enlighten me?

Edit: Although I guess it is not relevant for the question: I used g++ 4.9 and clang 3.5 (both repo HEADs)

like image 770
Richard Vock Avatar asked Jan 09 '14 14:01

Richard Vock


People also ask

What is a universal reference?

Universal reference was a term Scott Meyers coined to describe the concept of taking an rvalue reference to a cv-unqualified template parameter, which can then be deduced as either a value or an lvalue reference.

What are template parameters?

In UML models, template parameters are formal parameters that once bound to actual values, called template arguments, make templates usable model elements. You can use template parameters to create general definitions of particular types of template.


1 Answers

"Universal reference" is a colloquialism, and it always means, strictly, a reference T && where T is a deduced template parameter.

You can modify your code, though, to use just that:

template <typename T>
void func(T && c) { /* ... std::forward<T>(c) ... */ }

If you care that T is of the specified form, add a trait:

#include <type_traits>

template <typename T>
typename std::enable_if<IsATemplate<typename std::decay<T>::type>::value>::type
func(T && c) { /* ... std::forward<T>(c) ... */ }

Writing the IsATemplate trait is left as an exercise.

like image 116
Kerrek SB Avatar answered Oct 19 '22 13:10

Kerrek SB