【发布时间】:2020-10-03 19:52:28
【问题描述】:
考虑以下sn-p
#include <type_traits>
template <typename T>
concept unsigned_integral = std::is_integral_v<T> &&std::is_unsigned_v<T>;
template <unsigned_integral T>
auto test(T) -> std::make_signed_t<T>; //(1)
template <typename T>
auto test(T) -> int; //(2)
int sandbox() {
test(1u); // Call to (1) as expected
test(1.0); // Expected to call (2), compilers choose (1) and fail to compile
}
MSVC 14.26、GCC-10 和 Clang-10 都无法编译这个,所以我想标准使它成为无效代码,所以这应该被认为是标准的疏忽吗?因为使用 SFINAE,代码按预期编译。
SFINAE 版本(这只适用于 double 案例,因为 unsigned int 案例会有歧义,但这不会影响我提出的问题)
template <typename T, typename = std::enable_if_t<unsigned_integral<T>>>
auto test(T) -> std::make_signed_t<T>;
编辑:显然,这与尾随返回类型无关,因此我已将标题更改为适当的标题。
【问题讨论】:
-
您的等效 SFINAE 版本是什么?因为这很可能是这里的复杂点
-
编译器不会选择 (1),他们只是考虑它,并在这样做的同时将
double替换为std::make_unsigned_t(由于某种原因,这对 SFINAE 不友好)。跨度> -
@HolyBlackCat 但它应该作为 SFINAE 工作,因为如果第一次考虑失败,则应考虑下一个候选人,但事实并非如此
-
@StoryTeller-UnslanderMonica 我刚刚添加了 SFINAE 版本
-
@UyHà SFINAE 不会捕获所有错误。它只适用于所谓的即时上下文中的错误,其他错误仍然会中止编译。
标签: c++ c++20 c++-concepts