错误:类型为'bar <int>&'的参数的默认参数有类型'bar <int>'

kni*_*ils 2 c++ templates c++11

我在编译时遇到上述错误,如何纠正它.请帮我解决这个问题

#include <iostream>
using namespace std;

template <typename T>
class bar
{
 public:
 bar(){cout << "bar" <<"\n";}
};

template <typename T, typename ctor = bar<T>>
class foo
{
 T i;
public:
 explicit foo(ctor& c = ctor());
private:
 ctor mctor;


};

template <typename T, typename ctor>
foo<T,ctor>::foo(ctor& c):mctor(c)
{
 cout << "foo" <<"\n";
}

int main()
{
 foo<int> f;
 return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译:g ++ -std = c ++ 11 ctor_call.cpp

Mik*_*ike 6

你给出了一个参数的默认参数,该参数应该在这一行中通过引用传递:

explicit foo(ctor& c = ctor());
Run Code Online (Sandbox Code Playgroud)

这里ctor&是对类型对象的引用ctor.因此,只要您有对象的引用,该对象就需要存在.但是默认参数将它设置为一个即将被销毁的临时对象.而且由于临时对象没有标准化,它可能会在构造函数开始之前被销毁,所以你不会有任何引用.在这个答案对这一切有一个很好的解释.

模板的情况稍微复杂一些,所以让我们更具体一点.默认ctor()是对您正在引用的对象的构造函数的调用.在你的情况下,类是foo<int>,所以模板看起来像

template <int, typename ctor = bar<int>>
class foo
Run Code Online (Sandbox Code Playgroud)

这里,模板得到第二个参数,但它是默认参数,所以你得到了ctor = bar<int>.这相当于使用foo<int, bar<int>>.现在,在函数语句中,ctor()它实际上是相同的bar<int>()- 它是对构造函数的调用.

一些可能的解决方案

1)不要传递默认值:

explicit foo(ctor& c);
Run Code Online (Sandbox Code Playgroud)

2)不要参考:

explicit foo(ctor c = ctor());
Run Code Online (Sandbox Code Playgroud)

3)通过const参考:

explicit foo(const ctor& c = ctor());
Run Code Online (Sandbox Code Playgroud)

这有点神奇,因为它const使编译器保持临时对象,直到const引用被销毁,这是在结束时foo构造函数调用.

4)使用存在于foo对象外部的东西,例如静态或全局对象.(虽然你应该警惕静态,我们基本上都讨厌全局...):

explicit foo(ctor& c = some_ctor_object_that_exists_already);
Run Code Online (Sandbox Code Playgroud)