【问题标题】:Specialized template accepting constructor parameter when only default constructor defined仅定义默认构造函数时接受构造函数参数的专用模板
【发布时间】:2019-07-30 02:12:48
【问题描述】:

所以,我有这个模板类及其专业化。

    #include <iostream>

    using namespace std;

    template<bool> struct CompileTimeChecker{

         CompileTimeChecker(...); //constructor, can accept any number of parameters;

    };

    //specialized template definition

    template<> struct CompileTimeChecker<false> {

        //default constructor, body empty

    };

案例 1:

main 函数中,我定义了一个名为ErrorA 的本地类。当我创建一个 CompileTimeChecker&lt;false&gt; 的临时对象并将 ErrorA 的临时对象作为初始值设定项时,编译器没有检测到任何错误。

int main()
{

    class ErrorA {};

    CompileTimeChecker<false>(ErrorA()); //Case 1;

    CompileTimeChecker<false>(int());    //Case 2;

    return 0;

}

案例 2:

接下来我用int 类型的临时对象输入它,然后编译器突然发现了这个问题(在专用模板CompileTimeChecker&lt;false&gt; 中没有使用args 的构造函数)

main.cpp:30:36: error: no matching function for call to ‘CompileTimeChecker::CompileTimeChecker(int)’ CompileTimeChecker<false>(int());

main.cpp:21:23: note: candidate: constexpr CompileTimeChecker::CompileTimeChecker()
     template<> struct CompileTimeChecker<false> {
                       ^~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:21:23: note:   candidate expects 0 arguments, 1 provided

为什么它无法识别案例 1 中的问题?

【问题讨论】:

    标签: c++11


    【解决方案1】:
    CompileTimeChecker<false>(ErrorA());
    

    不会创建CompileTimeChecker&lt;false&gt; 类型的临时对象,而是将临时ErrorA() 传递给其构造函数。相反,它声明了一个名为 ErrorA 的函数,不接受任何参数并返回 CompileTimeChecker&lt;false&gt; 。另见:most vexing parse

    另一方面,CompileTimeChecker&lt;false&gt;(int()); 不能被解析为声明,因此它确实创建了一个 CompileTimeChecker&lt;false&gt; 类型的临时变量。

    最简单的方法是用大括号代替括号来表示初始化:

    CompileTimeChecker<false>{ErrorA{}};
    

    【讨论】:

    • 与这个答案一致,我稍微修改“案例1”以减少模糊,并得到错误。 coliru.stacked-crooked.com/a/26e9cfaf94d212e3 ;顺便说一句,好问题和好答案。
    • @javaLover 只需 CompileTimeChecker&lt;false&gt;{ErrorA{}}; 即可。 C++11 中的统一初始化旨在避免最棘手的解析等问题。
    • 很好的解释和参考!另外,在这种情况下双括号就足够了(如链接的参考所建议的那样)@javaLover?
    • @User10482 我不确定你的意思,但 Igor 的解决方案 {ErrorA{}} 应该可以工作而且很漂亮。
    • {class ERROR; (void)sizeof(CompilerTimeChecker&lt;(expr) !=0&gt;((ERROR())));} 这是 Andrei 的《现代 C++ 设计》一书的节选。我倾向于认为ERROR() 的多余括号是为了防止歧义。 @javaLover @IgorTandetnik
    猜你喜欢
    • 2016-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-27
    • 1970-01-01
    • 2014-05-18
    • 1970-01-01
    • 2011-07-15
    相关资源
    最近更新 更多