【发布时间】:2021-12-08 01:38:41
【问题描述】:
受this answer 的启发,我生成了这段代码,其输出取决于编译器:
template <typename... Args>
constexpr auto foo(Args&& ...args, ...) noexcept {
return sizeof...(args);
}
constexpr auto bar() noexcept {
return (&foo<int>)(1, 2);
}
如果使用 GCC 11 编译,bar 调用 foo<int> 并返回 1,而 clang 13 和 MSVC 2019 都推导出 foo<int, int> 和 bar 返回 2。
这是我在 Godbolt 上的沙盒:https://godbolt.org/z/MedvvbzqG。
哪个输出是正确的?
编辑:
如果我直接使用return foo<int>(1, 2);,即与
constexpr auto bar() noexcept {
return foo<int>(1, 2);
}
【问题讨论】:
-
我会说gcc,因为
(&foo<int>)应该先做,所以不能使用后面的推论... -
我认为 Clang 和 MSVC 正在为自己的优化而绊倒。获取地址并立即调用常规函数可以内联到......只是调用它。然而,这并不适用于此,因为现在获取地址首先会影响行为。
-
确实,在混合中添加一个临时变量
auto p = &foo<int>;会使 Clang 和 MSVC 的行为符合预期。 -
@StoryTeller-UnslanderMonica:[over.match.call.general]/2 表示可以针对重载集的地址进行重载解析,因此模板参数推导可以在此处非常合理地发生。跨度>
-
@DavisHerring - 我们对“合理”的定义不一致。
标签: c++ language-lawyer variadic-templates variadic-functions template-argument-deduction