c++c++14c++17template-templatesvariable-templates

Variable template template?


Say you have a tuple type and you want to extract its template parameter pack in order to instantiate another template. If that is a type template, then I can have a utility like this:

template < typename Tuple, template <typename...> typename What >
struct PutTupleInT;

template < typename... Types, template <typename...> typename What >
struct PutTupleInT<std::tuple<Types...>, What>
{
    using Result = What<Types...>;
};

But what if the desired template is a variable template? While template <typename...> typename What is the "placeholder" for a type template, then what is the "placeholder" for a variable template?

I've tried the following for clang-4.0.0 (the only compiler by now that supports non-type template parameters with auto type), but it failed. Actually I am not sure if this is a correct syntax for C++17.

template < typename Tuple, template <typename...> auto What >
struct PutTupleInV;

template < typename... Types, template <typename...> auto What >
struct PutTupleInV<std::tuple<Types...>, What>
{
    static constexpr auto value = What<Types...>;
};

Solution

  • I don't think you can do that. Quoting N4606:

    §14.3.3 [temp.arg.template]/1

    A template-argument for a template template-parameter shall be the name of a class template or an alias template, expressed as id-expression.

    A variable template doesn't fit this requirement.


    You could cheat a little and use a proxy type to select the template:

    template < typename Tuple, class Proxy>
    struct PutTupleInTV;
    
    template < typename... Types, class Proxy>
    struct PutTupleInTV<std::tuple<Types...>, Proxy>
    {
        static constexpr auto value = Proxy::template value<Types...>;
    };
    

    and then for

    template<typename...> struct foo{};
    template<typename... Ts> constexpr foo<Ts...> foo_v{};
    struct use_foo
    {
        template<typename... Ts>
        static constexpr auto value = foo_v<Ts...>;
    };
    

    you could say

    PutTupleInTV<tup, use_foo>::value
    

    live demo