为什么将lambda用于非类型模板参数时gcc失败? [英] Why is gcc failing when using lambda for non-type template parameter?

查看:100
本文介绍了为什么将lambda用于非类型模板参数时gcc失败?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下代码段编译,在Clang 4.0中没有错误,但GCC 7.0生成了错误(请注意-std = c ++ 1z标志的使用)。

The following snippet compiles with no error with Clang 4.0 but GCC 7.0 produces errors (note the use of -std=c++1z flag).

using FuncT = int (*)(double);

template <FuncT FUNC>
int temp_foo(double a)
{
    return FUNC(a);
}

int foo(double a)
{
    return 42;
}

void func()
{
    auto lambda = [](double a) { return 5; };

    struct MyStruct
    {
        static int foo(double a) { return 42; }
    };

    temp_foo<foo>(3);
    temp_foo<static_cast<FuncT>(lambda)>(3);
    temp_foo<MyStruct::foo>(3);
}

特别是,GCC抱怨lambda和嵌套类的方法都没有链接,因此不能将它们用作非类型模板参数。

Specifically, GCC complains that both the lambda and the nested class's method have no linkage, so they can't be used as a non-type template argument.

至少对于lambda情况,我认为Clang是正确的(而GCC是错误的),因为(引自转换操作符 cppreference ):

At least for the lambda case I think that Clang is correct (and GCC is wrong) since (quoting from cppreference, the conversion operator):


此转换函数返回的值是指向具有C ++语言链接的
函数的指针,该函数在被调用时具有与
相同的效果直接调用闭包对象的函数调用运算符

The value returned by this conversion function is a pointer to a function with C++ language linkage that, when invoked, has the same effect as invoking the closure object's function call operator directly.

GCC行为不正常吗?

Is GCC misbehaving?

推荐答案

根据 http://en.cppreference.com/w/cpp/language/template_parameters#Non-t ype_template_parameter ,自C ++ 17起,似乎不再需要外部链接。在C ++ 17草案的[temp.arg.nontype]下的 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf (请注意,该链接被错误地链接为C ++ 14草案)。

According to http://en.cppreference.com/w/cpp/language/template_parameters#Non-type_template_parameter, it seems like external linkage is no longer a requirement since C++17. The same language is found in the C++17 draft under [temp.arg.nontype] at http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf (note that it is incorrectly linked as a C++14 draft).


可以与非类型模板参数一起使用的模板参数可以是任何转换后的常量表达式

The template argument that can be used with a non-type template parameter can be any converted constant expression of the type of the template parameter...

唯一的例外是引用和指针类型的非类型模板参数不能引用/不是其地址

The only exceptions are that non-type template parameters of reference and pointer type cannot refer to/be the address of


  • 子对象(包括非静态类成员,基础子对象或数组
    元素);

  • 一个临时对象(包括在引用初始化期间创建的对象);

  • 字符串文字;

  • typeid的结果;

  • 或预定义变量__func __。

  • a subobject (including non-static class member, base subobject, or array element);
  • a temporary object (including one created during reference initialization);
  • a string literal;
  • the result of typeid;
  • or the predefined variable __func__.

在cppreference上的链接还专门提到了函数指针,在C ++ 17之前:

That link on cppreference also specifically mentions function pointers, pre C++ 17:


实例化具有非类型模板参数的模板时,存在以下限制:

The following limitations apply when instantiating templates that have non-type template parameters:

...

对于函数指针,有效参数是具有链接功能的指针(或计算为空指针值的常量表达式)。

For pointers to functions, the valid arguments are pointers to functions with linkage (or constant expressions that evaluate to null pointer values).

因为您的问题被标记为C ++ 1z(我们现在应该已经有一个17标记,并且因为17结束才使用该标记),所以我们应该使用第一组规则。您的示例似乎没有属于C ++ 17的任何异常类别,因此gcc错误。

Since your question is labelled C++1z (we should probably have a 17 tag by now and use that instead since 17 is finished) we should use the first set of rules. Your example does not seem to fall into any of the exception categories for C++ 17, and therefore gcc is in error.

请注意,如果更改,clang不会编译您的示例语言标记为14。

Note that clang does not compile your example if you change the language flag to 14.

这篇关于为什么将lambda用于非类型模板参数时gcc失败?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆