Search code examples
c++templatesc++11using

How to send a template to another template without declaring the type?


I'm trying to compile following code :

#include <iostream>

template<class T> struct Container1;//forward declaration
template<class T> struct Container2;//forward declaration

template<class Container,class Type>
using _Make_Container=typename Container<Type>;

template<class T>
struct Container1
{};

template<class T>
struct Container2
{};

int main()
{
    _Make_Container<Container1,int> a;
}

Which give me some errors:

 expected nested-name-specifier before 'Container'
  using _Make_Container=typename Container<Type>;
                                ^
 error: 'Container' is not a template

It seems OK to me because we send Container1 and int to using Then it becomes :

using _Make_Container=typename Container1<int>;
//then 
Container1<int> a;

I can't understand the reason for that errors !! Any idea?

Is there any way for making that works ?


Solution

  • Those error messages are pretty clear.

    expected nested-name-specifier before 'Container'

     using _Make_Container=typename Container<Type>;
                              ^
    

    You're not referring to a nested dependent type so there's no need for the typename keyword here. Read this for a detailed explanation on where typename is required.

    error: 'Container' is not a template

    Just like it says, your alias template doesn't indicate Container is a template, but then it proceeds to use it as one. You need to use a template template parameter for Container

    template<template<typename> class Container,class Type>
    using _Make_Container = Container<Type>;
    

    And borrowing Yakk's excellent suggestion, you should change the alias template definition to

    template<template <typename...> class T1, typename... T2>
    using Make_Container = T1<T2...>;
    

    This lets you do the following:

    template<class T, class T1>
    struct Container2
    {};
    
    Make_Container<Container2,int,long> b;
    

    Finally, names using a leading underscore followed by an upper case letter are reserved by the implementation. So you should rename _Make_Container to Make_Container.