【问题标题】:C++ variadic template specialization (and static_assert)C++ 可变参数模板特化(和 static_assert)
【发布时间】:2016-07-12 22:13:33
【问题描述】:

是否可以专门化这个模板声明:

template <class TYPE, class... ARGS> TYPE Foo(ARGS... args) { 
    static_assert(false);
}

我尝试了一些方法,例如:

template <> int Foo<int>(float args) {
    return 42;
}

...但是当我尝试这样使用它时,我总是点击静态断言:

auto value = Foo<int>(1.5f);

正确的语法是什么?

【问题讨论】:

  • 也许只是你的编译器不支持它,就像在这个答案中一样:stackoverflow.com/questions/7767202/… ?
  • 您使用哪个编译器? Clang 和 MSVC 会编译你的代码,value 持有 42。

标签: c++ templates variadic-templates


【解决方案1】:

您不能编写仅在未实例化时才有效的模板。这违反了标准中的以下规则:

如果没有有效的专业化可以 为模板生成,并且该模板未实例化,模板格式错误,无诊断 必填。

另一方面,如果你的身体里有一些东西,比如

static_assert(sizeof(TYPE) != sizeof(int));

在这种情况下,模板是有效的,并且您的代码将编译,因为实际上将使用显式特化而不是主模板。见http://coliru.stacked-crooked.com/a/238b979fd10c62c0

【讨论】:

    【解决方案2】:

    作为状态,false 不依赖于模板,因此static_assert 应该触发。

    您可以在您的情况下使用= delete

    template <class TYPE, class... ARGS> TYPE Foo(ARGS... args) = delete;
    
    template <> int Foo(float) {return 42;}
    

    Demo

    【讨论】:

    • 这种情况下template &lt;class TYPE, class... ARGS&gt; TYPE Foo(ARGS... args);不够用吗?
    • @skypjack: 可能是链接错误,而=delete 可能会出现编译错误。
    • 在现场演示中运行良好,但在 Visual Studio 2015 Update 2 中不起作用。我收到 error C2280: attempting to reference a deleted function
    【解决方案3】:

    您的静态断言不依赖于模板,因此它总是会触发。使用类似的东西

    template <class TYPE, class... ARGS> TYPE Foo(ARGS... args) { 
        static_assert(sizeof(TYPE) != sizeof(TYPE));
    }
    

    【讨论】:

    • 即使编译器当前没有诊断它,这也同样糟糕。
    • @TC:它确实可以正确诊断它 - 对失败的 static_assert 的正确诊断是错误的......正如标准所述,static_assert 失败的编译阶段处于非依赖表达式的模板定义和依赖表达式的实例化。因此,如果您希望 static_assert 仅在实例化时触发,请使其依赖,即使条件本身不受模板参数的影响。
    • 由于无法生成此模板的有效特化,因此允许编译器在定义时对此进行诊断。引用在布莱恩的回答中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-10-15
    • 2016-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多