【问题标题】:Interesting behaviour when calling constructor in templated constructor在模板化构造函数中调用构造函数时的有趣行为
【发布时间】:2015-01-20 21:28:33
【问题描述】:

我刚刚创建了一个非常小的项目,当我遇到一个我无法追踪的有趣的编译器错误时,我认为我可以立即完成(它是关于基本委托的)。这是代码的简化版本:

class NoComp {
};

class Comp {
    bool operator==(const Comp& other)
    { std::cout << "Working!" << std::endl; return true;}
};

struct Test {
    template<typename T>
    Test(T&& obj) {}
    bool operator==(const Test& other);
};
int main()
{
    Test a(Comp());
    Test b(NoComp());
    a.operator ==(b);
}

使用g++ version 4.8.3 20140911 (Red Hat 4.8.3-7) (GCC) found here 编译时会产生以下编译器错误:

main.cpp: In function 'int main()':                                    
main.cpp:22:13: error: request for member 'operator==' in 'a', which is
 of non-class type 'Test(Comp (*)())'                                  
  a.operator ==(b);                                                    

我无法弄清楚该错误的含义以及它为什么存在。那里发生了什么,它是一个错误还是被标准覆盖?如果可以的话,我该如何躲避呢?

【问题讨论】:

  • 最麻烦的解析...
  • 是的 - 你在声明一个类型
  • ...一个函数,而不是
  • 有一个类似的问题:Compiler optimization or my misunderstanding。请注意,正如我在回答中所展示的那样,clang 会给您一个非常有用的警告,在多个编译器中尝试示例通常会有所帮助。

标签: c++ templates c++11 compiler-errors


【解决方案1】:
Test a(Comp());
Test b(NoComp());

这声明了两个名为ab 的函数。第一个具有Comp(*)() 类型的参数和Test 的返回类型,第二个采用NoComp(*)() 并返回TestComp() 是一个函数类型,并且作为函数类型的所有参数,调整为指向函数的类型。 NoComp() 也是如此。

使用双括号:

Test a((Comp()));
Test b((NoComp()));

或从 C++11 开始的列表初始化。

【讨论】:

    【解决方案2】:

    你有所谓的most vexing parse

    线条

    Test a(Comp());
    Test b(NoComp());
    

    不声明变量,但有两个函数 ab,采用一个指向函数的指针,该函数返回 Comp (NoComp) 并且不接受任何参数。

    如果您可以访问 C++11,请使用列表初始化,即

    Test a{Comp()};
    Test b{NoComp()};
    

    如果不这样做,请使用双括号

    Test a((Comp()));
    Test b((NoComp()));
    

    【讨论】:

    • 我以前从未见过双括号。它有什么缺点吗? (除了占用空间?)。如果我只是机械地使用(( 来环绕对构造函数的每次调用,它会一直有效吗?例如X * xp = new X(( Comp(()), NoComp(()) )) ?
    猜你喜欢
    • 2019-03-14
    • 2011-05-24
    • 1970-01-01
    • 2021-11-11
    • 1970-01-01
    • 2012-08-12
    • 1970-01-01
    • 1970-01-01
    • 2019-10-08
    相关资源
    最近更新 更多