【发布时间】:2017-03-28 08:55:34
【问题描述】:
以下代码使用 gcc 和 MSVC 编译,但使用 clang-3.5 和当前主干测试的 clang 失败)。
template <typename T>
constexpr auto wrong = false;
template <typename T>
constexpr auto foo(const T t) -> int
{
static_assert(wrong<T>, "");
return {};
}
using F = decltype(foo(1));
int main() {}
clang 实例化函数体并偶然发现static_assert。 gcc 和 MSVC 只看函数声明,忽略正文中的static_assert。
如果去掉 constexpr,所有编译器都可以正常编译代码。
问题:
如果声明了返回类型,是否允许 decltype 查看函数体?
我正在寻找对标准中相应部分的参考。
【问题讨论】:
-
我认为更好的方法是:
decltype触发模板实例化吗? -
@BoPersson 如果不实例化主体,编译器无法判断。
wrong可能有一个特化,即true。 -
@RyanHaining 在大多数情况下,它不会。正如问题中所写:如果删除
constexpr,则没有编译器实例化主体。 -
"[temp.inst]/3 ...当在需要函数定义存在的上下文中引用特化时,函数模板特化被隐式实例化。"这似乎表明,如果一段代码仅使用可用函数模板的声明而不是定义进行编译,那么该段代码不应触发隐式实例化。 Clang 违反了这个不变量 - 工作 with declaration alone,失败 with definition。在我未经训练的眼睛看来,这就像一个错误。
-
搜索clang bug库,得知该主题有一个未解决的核心问题:open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1581
标签: c++ templates clang language-lawyer constexpr