1

我创建了一个看起来像这样的类。关键是它有一个主模板参数和一个带有默认值的模板基类。还有一个模板化的复制构造函数......

struct default_base{};

template <typename T, typename TBase=default_base>
class some_class : public TBase{
public:
    some_class(){}
    template <typename U, typename UBase>
    some_class(const some_class<U,UBase>& u){
        T t(U());
    }
};


int main(){
    some_class<int> a;
    return 0;
}

我收到了这个令人讨厌的模糊编译器错误,并且无法发现我的错误......所以我的问题是 - 到底出了什么问题?我正在使用 gcc 4.8.1。

g++ -O0 -g3 -Wall -c -fmessage-length=0 -o "src\\stuff.o" "..\\src\\stuff.cpp" 
..\src\stuff.cpp: In constructor 'some_class<T, TBase>::some_class(const some_class<U,     UBase>&)':
..\src\stuff.cpp:87:10: error: default argument for template parameter for class     enclosing 'T t(U (*)())'
   T t(U());
      ^
..\src\stuff.cpp: In function 'int main()':
..\src\stuff.cpp:104:16: error: wrong number of template arguments (1, should be 2)
  some_class<int> a;
            ^
..\src\stuff.cpp:82:7: error: provided for 'template<class T, class TBase> class   some_class'
 class some_class : public TBase{
   ^
..\src\stuff.cpp:104:19: error: invalid type in declaration before ';' token
  some_class<int> a;

编辑:找到答案,干杯:-)即使我仍然认为它应该编译......这编译......

template <typename T>
struct some_other_class{
some_other_class(){}
    template <typename U>
    some_other_class(){
        T t(U());
    }
};
4

2 回答 2

7
T t(U());

这就是所谓的“最令人头疼的解析”。它是返回 T 的函数声明,并采用返回 U 作为参数的空函数。想象:

typedef U nullary_function_return_U();
T t(nullary_function_return_U /*param_name*/)
{
    return T;
}

您可以通过添加括号来解决它:

T t( (U()) );

或者在 C++11 中,您可以使用统一的初始化语法:

T t{U{}};

确实是最令人烦恼的。错误消息真的很糟糕,无论最令人烦恼的解析如何,它都应该真正编译,不是吗?

我已经在 GCC 4.8.1 上测试过 - 错误,Clang 3.4 - OK,MSVC2010 - OK。我将其缩减为在GCC上触发错误的最小情况:

template <typename = int>
struct Foo
{
    Foo()
    {
        int t(int()); // Error
    }
};

int main()
{
    int t(int()); // OK
    Foo<> a; // Error
}

这看起来像 GCC 错误。我已向GCC Bugzilla报告。


编辑

Paolo Carlini 2014-07-07 14:11:14 UTC 这已经是固定的主线和 4.9.1。我正在添加测试用例并关闭错误。

于 2013-10-28T00:18:35.010 回答
1

你真的要声明一个名为 的函数t,将一个函数U作为参数返回,然后返回T吗?当使用例如消除声明以声明变量t时,

T t{U()};

似乎 gcc 对声明很满意。

于 2013-10-28T00:27:32.727 回答