2

所以我尝试编译下面的代码,但它失败了(如预期的那样):

1.cpp: In function ‘int foo()’:
1.cpp:3:5: error: ‘some’ was not declared in this scope
     some ill-formed code
     ^

但是如果我删除这一行,编译器会编译它而不会出现任何错误(也可以预期,因为T类型是否有random_name()方法是未知的)。

似乎未使用(未实例化)的模板的诊断在某种程度上是实现定义的。但也许标准对这种情况有一些要求。例如,编译下面的代码是否符合标准而没有任何错误?

我试图在网站上搜索答案,但找不到任何相关问题。

template <class T>
int foo() {
    some ill-formed code
    return T::random_name();
}

template <>
int foo<int>() { return 0; }

int main() {
    return foo<int>();
}
4

2 回答 2

6

这是实施质量问题,格式不正确,但如果未实例化,则不需要根据[temp.res#8.1]p进行诊断:

可以在任何实例化之前检查模板的有效性。[注意:知道哪些名称是类型名称允许以这种方式检查每个模板的语法。— 尾注]程序格式错误,无需诊断,如果

  • 无法为模板或 constexpr if 语句的子语句生成有效的特化模板内的语句并且模板未实例化,或

我们可以从这个活的godbolt示例中看到MSVC没有诊断出这种情况。这是因为MSVC 没有使用两阶段查找,而是使用了/permissive-更改。clang 甚至有一个MSVC 兼容模式可以使用-fdelayed-template-parsing.

我们可以从这个 live godbolt 中看到,使用这两个选项clang 不再产生诊断,但 MSVC 可以。

于 2018-11-26T02:30:59.490 回答
0

函数内部的名称template要么是依赖的,即实体依赖template于某种形式的参数,要么是独立的,即没有迹象表明它依赖于template参数。定义函数时会查找独立名称template。在实例化期间查找从属名称template,即在定义函数时不需要定义名称template。查找名称失败是一个错误。这个过程的细节涉及更多,并且占据了关于templates 的大部分章节。

在你的情况下some是一个独立的名字,而T::资格是random_name一个从属的名字。

于 2018-11-26T02:38:38.727 回答