【发布时间】:2021-11-06 03:03:09
【问题描述】:
struct incomplete_type;
#if 0
struct incomplete_type {
static void foo() {}
};
#endif
template<typename T>
struct problem_type
{
constexpr problem_type(int) noexcept {};
constexpr problem_type(double) noexcept : problem_type(5) {}
~problem_type() {
T::foo();
}
};
void bar(problem_type<incomplete_type> arg=5.0) noexcept;
当bar 有一个调用转发构造函数的默认参数也是constexpr 时,编译器也会尝试实例化析构函数,但失败了,因为T::foo 不能被调用,因为T 是不完整的类型.
如果默认参数没有调用转发构造函数(例如,如果我们将5.0 更改为5),如果转发构造函数不是constexpr,或者(当然)如果类型T 至此完成。
如果析构函数是constexpr,也会出现问题,即使构造函数没有转发。
noexcept 似乎无关紧要,但我将其保留以确保编译器不会尝试生成堆栈展开代码。
这只发生在 clang (12.0.1) 上,而不是 gcc (11.2) 或 Visual Studio (19.29)。见godbolt
请注意,函数bar没有定义或调用。
为什么这不能在 clang 中编译?
【问题讨论】:
-
听起来像一个错误,默认参数是在调用者的上下文中评估的。可能相关:bugs.llvm.org/show_bug.cgi?id=42303
-
似乎是作为类模板实例化的一部分,[temp.inst]/11 可能允许,它试图确定
problem_type(double)是否实际上是该专业化的constexpr。
标签: c++ language-lawyer