铛错误:非类型模板参数是指没有联系的函数 - 错误? [英] clang error: non-type template argument refers to function that does not have linkage -- bug?

查看:131
本文介绍了铛错误:非类型模板参数是指没有联系的函数 - 错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些非常简单的( C ++ 11 )代码,最新的 clang version 3.4 trunk 187493 )无法编译,但GCC编译正常。



下面的代码用函数实例化函数模板 foo - 本地类型 Bar ,然后尝试将其地址用作类模板 Func

 模板< void(* FUNC_PTR)(void)> 
struct Func {};

模板< typename T> extern inline
void foo(){
using Foo = Func< foo< T>> ;;
}
int main(){
struct Bar {}; //函数本地类型
foo< Bar>();
返回0;

clang会发出以下错误:


错误:非类型模板参数指的是函数'foo':
没有链接<但是,如果将类型 Bar 移动到全局范围内(通过将其从<全局范围>中删除)函数),然后铿锵编译它罚款,证明问题是类型为函数本地



因此是铛正确发射这个错误,还是该标准不支持这个(在这种情况下,海湾合作委员会由于过于宽松,允许它)?



编辑#1:要清楚,这是不是重复这个问题,因为'不能使用本地类型作为模板参数'限制在C ++ 11中被删除。 然而,使用本地类型是否存在链接影响,以及铿锵是否正确发布此错误还不清楚。



编辑#2:已经确定clang对于上述代码发出错误是正确的(请参阅@jxh的回答),但是 还会为以下代码(使用使用声明从 foo< Bar>()>移除)范围为 main()范围):
$ b

 模板< void(* FUNC_PTR)(无效)> 
struct Func {};

模板< typename T> extern inline
void foo(){}

int main(){
struct Bar {};
使用F = Func< foo< Bar>>;
返回0;


解决方案

没有链接在C ++中。11  3.5 程序和链接¶ 2,我原本认为 foo< Bar> 因为除了定义类型 Bar (即, main())。但是,这是不正确的。这是因为外部链接的名称定义描述为:


当名称外部链接,它表示的实体可以通过其他翻译单元的范围中的名称或相同翻译单元的其他范围中的名称引用。


而对于模板函数,情况总是如此。这是因为还有一个其他范围可以引用该名称。即,模板函数可以引用它自己。因此, foo< Bar> 具有外部链接。 zneak的回答,编辑2 ,与叮当开发者通过电子邮件线索确认 foo< Bar> 应该有外部链接。



因此,从C ++。11§ 14.3.2 模板非类型参数&1;


模板参数适用于非类型的非模板 template-parameter 应为以下之一:...

  • 常量表达式(5.19)指定具有静态存储持续时间和外部或内部链接的对象的地址或具有外部或内部链接,包括函数模板和函数 template-id ,但不包括非静态类成员,表达(忽略圆括号)为& id-expression ,除非& 可以省略,如果名称引用一个函数或数组,并且如果相应的模板参数是一个参考; ...


  • 最相关的项目符号是第三个项目符号。由于 foo< bar> 具有外部链接,因此将它作为非类型的模板参数传递应该没有问题。


    I have some very simple (C++11) code which the latest clang (version 3.4 trunk 187493) fails to compile, but GCC compiles fine.

    The code (below) instantiates the function-template foo with the function-local type Bar and then tries to use its address as a non-type template parameter for the class-template Func:

    template<void(*FUNC_PTR)(void)>
    struct Func {};
    
    template<typename T> extern inline
    void foo() {
        using Foo = Func<foo<T>>;
    }
    int main() {
        struct Bar {}; // function-local type
        foo<Bar>();
        return 0;
    }
    

    clang emits the following error:

    error: non-type template argument refers to function 'foo' that does not have linkage

    However, if I move type Bar to global scope (by taking it out of the function), then clang compiles it fine, proving the issue is with the type being function-local.

    So is clang correct to emit this error, or does the standard not support this (in which case GCC is being too lenient by allowing it)?


    EDIT #1 : To be clear, this is not a duplicate of this question since the 'cannot use local types as template parameters' restriction was removed in C++11. However, it's still unclear if there are linkage implications involved with using a local type, and whether clang is correct or not in emitting this error.


    EDIT #2 : It has been determined that clang was correct to emit the error for the above code (see answer from @jxh), but that it incorrectly also emits an error for the following code (with using declaration moved from foo<Bar>() scope to main() scope):

    template<void(*FUNC_PTR)(void)>
    struct Func {};
    
    template<typename T> extern inline
    void foo() {}
    
    int main() {
        struct Bar {};
        using F = Func<foo<Bar>>;
        return 0;
    }
    

    解决方案

    By definition of no linkage in C++.11 §3.5 Program and linkage ¶2, I originally believed foo<Bar> has no linkage since it cannot be referred to by name by any other scope except that which defined the type Bar (ie, main()). However, this is not correct. This is because the definition of a name with external linkage is described as:

    When a name has external linkage, the entity it denotes can be referred to by names from scopes of other translation units or from other scopes of the same translation unit.

    And for a template function, this will always be the case. This is because there is one other scope from which the name can be referred. Namely, the template function can refer to itself. Therefore, foo<Bar> has external linkage. zneak's answer, EDIT 2, has an e-mail thread with the clang developers confirming that foo<Bar> should have external linkage.

    Thus, from C++.11 §14.3.2 Template non-type arguments ¶1:

    A template-argument for a non-type, non-template template-parameter shall be one of: ...

  • a constant expression (5.19) that designates the address of an object with static storage duration and external or internal linkage or a function with external or internal linkage, including function templates and function template-ids but excluding non-static class members, expressed (ignoring parentheses) as &id-expression, except that the & may be omitted if the name refers to a function or array and shall be omitted if the corresponding template-parameter is a reference; ...

  • The most relevant bullet is the third bullet. Since foo<bar> has external linkage, passing it as a non-type template-parameter should be fine.

    这篇关于铛错误:非类型模板参数是指没有联系的函数 - 错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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