【问题标题】:C++ template compile failedC++ 模板编译失败
【发布时间】:2022-02-01 07:21:43
【问题描述】:

我想写一个简单的demo,但是编译失败,找不到原因。

#include <iostream>
#include <vector>
#include <list>
using namespace std;


template <
    typename T,  
    template <typename W> typename  Container = std::vector 
>
class myclass
{
public:
    Container<T> myc;

public:
    void func();
    myclass() 
    {
        for (int i = 0; i < 10; ++i)
        {
            myc.push_back(i);  
        }
    }
};

template <
    typename T,
    template <typename W> typename  Container 
>
void myclass<T, Container>::func()
{
    cout << "good!" << endl;
}


int main()
{
   
    myclass<int, vector> mylistobj2; 
    mylistobj2.func();


    return 0;
}

编译原因是这样的

tmp.cpp: In function ‘int main()’:
tmp.cpp:100:30: error: type/value mismatch at argument 2 in template parameter list for ‘template<class T, template<class W> class Container> class _nmsp1::myclass’
  100 |  _nmsp1::myclass<double, list> mylistobj2; 
      |                              ^
tmp.cpp:100:30: note:   expected a template of type ‘template<class W> class Container’, got ‘template<class _Tp, class _Alloc> class std::__cxx11::list’
tmp.cpp:101:13: error: request for member ‘func’ in ‘mylistobj2’, which is of non-class type ‘int’
  101 |  mylistobj2.func();

【问题讨论】:

  • The std::vector template 不接受单个模板参数。 std::list 也没有。不要使用模板模板参数,而是使用普通模板参数,比如普通的typename Container。然后在使用模板时使用正确的类型,例如myclass&lt;std::list&lt;double&gt;&gt;。如果您需要存储在容器中的类型(而不是您的 T),请使用 Container::value_type
  • 还有一个关于写好问题的说明:确保你得到的错误实际上与你显示的代码相匹配!你的没有。创建您的minimal reproducible example,然后复制粘贴该示例中的错误。
  • -std=c++17编译就可以了。
  • @PasserBy:虽然Demo没有clang。

标签: c++ list templates vector compiler-errors


【解决方案1】:

std::vector 有两个模板参数(第二个有默认参数),而模板模板参数Container 只声明了一个模板参数。他们不匹配。您可以申请parameter pack

template <
    typename T,  
    template <typename...> typename  Container = std::vector 
>
class myclass
{
public:
    Container<T> myc;

public:
    void func();
    myclass() 
    {
        for (int i = 0; i < 10; ++i)
        {
            myc.push_back(i);  
        }
    }
};

template <
    typename T,
    template <typename...> typename  Container 
>
void myclass<T, Container>::func()
{
    cout << "good!" << endl;
}

您的代码可以在 C++17 中正常工作;从 C++17 (CWG 150) 开始,template template argument 允许使用默认模板参数来匹配具有较少模板参数的模板模板参数。

【讨论】:

    【解决方案2】:

    问题在于在 C++17 之前

    模板模板参数必须是一个模板,其参数完全匹配模板模板参数的参数,但与可变参数模板参数相关的一些例外情况除外。

    在您给定的示例中,这意味着由于标准库的 std::vector 模板具有多个参数:第二个参数(描述 分配器)具有 默认值,但在 C++17 之前,在将 std::vectorContainer 参数匹配时不考虑这一点。

    有两种方法可以解决这个问题。

    解决方案 1

    一种解决方案是重写类myclass 声明,以便Container 参数需要具有两个模板参数的容器,如下所示:

    template <typename T,  
        template <typename W,typename Alloc = std::allocator<W>> typename  Container = std::vector> //note the second template parameter Alloc added here 
    
    class myclass
    {
    public:
        Container<T> myc;
    
    public:
        void func();
        myclass() 
        {
            for (int i = 0; i < 10; ++i)
            {
                myc.push_back(i);  
            }
        }
    };
    
    template <typename T,
        template <typename W, typename Alloc> typename  Container> //note the second template parameter here
    
    void myclass<T, Container>::func()
    {
        cout << "good!" << endl;
    }
    

    以上修改程序的输出可见here

    解决方案 2

    您可以使用参数包来解决这个问题。

    template <typename T,  
        template <typename...> typename  Container = std::vector> //note we have parameter pack
    
    class myclass
    {
    public:
        Container<T> myc;
    
    public:
        void func();
        myclass() 
        {
            for (int i = 0; i < 10; ++i)
            {
                myc.push_back(i);  
            }
        }
    };
    
    template <typename T,
        template <typename...> typename  Container> //note we have parameter pack 
    
    void myclass<T, Container>::func()
    {
        cout << "good!" << endl;
    }
    

    以上修改程序的输出可见here

    另请注意,您的程序 works 没有使用 C++17 进行任何修改。

    【讨论】:

      猜你喜欢
      • 2016-06-20
      • 1970-01-01
      • 1970-01-01
      • 2013-01-26
      • 1970-01-01
      • 2011-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多