gpt4 book ai didi

c++ - 导致 msvc 和 clang 中编译器错误的概念?

转载 作者:行者123 更新时间:2023-12-02 02:13:17 26 4
gpt4 key购买 nike

我有以下代码:

#include <variant>

template <typename T>
struct S{};

using Var = std::variant<S<int>, S<float>>;

template <typename T>
concept VariantMember = requires(Var var) { std::get<T>(var); };

void foo(VariantMember auto x) {}
void foo(auto x) {}

void bar()
{
foo(S<int>{});
foo(S<char>{});
}

MSVC 错误

error C2338: get(variant<Types...>&) requires T to occur exactly once in Types. (N4835 [variant.get]/5)

只有当我在本例中的变体 S 中使用同一模板的两个实例时,才会发生这种情况。因此,首先 std::get 意外出错,然后这个概念并没有失败,而是直接出错。有趣的是,如果我在概念之外使用 std::get ,例如:

std::get<S<int>>(Var{ S<int>{} });

代码编译良好。

Clang 似乎忽略了这个概念,并且在这两种情况下总是选择 foo 的第一个重载。

godbolt

这些实际上是错误还是我搞砸了?

最佳答案

首先,你的S模板是噪音。删除它。

using Var = std::variant<int, float>;

template <typename T>
concept VariantMember = requires(Var var) { std::get<T>(var); };

template <int = 1>
void foo(VariantMember auto x) {}

template <int = 2>
void foo(auto x) {}

void bar()
{
foo(int{});
foo(char{});
}

我们得到了同样的错误。如果我注释掉 char在这种情况下,它在 MSVC 中编译得很好。

std::get<char>(Var{})不需要对 SFINAE 友好。 std::get在这里,MSVC 可能(并且确实)出现硬故障。

在此版本中,clang 和 msvc 都调用 int=1一旦我删除 char 就会过载一个正在犯硬错误的人。

我们如何处理硬错误?写一个get事实并非如此; safe_get :

template<class T, class...Ts>
requires (1 == (std::is_same_v<T, Ts>+...))
T& safe_get( std::variant<Ts...>& var )
return std::get<T>(var);
}
template<class T, class...Ts>
requires (1 == (std::is_same_v<T, Ts>+...))
T const& safe_get( std::variant<Ts...> const& var )
return std::get<T>(var);
}
// ...
template <typename T>
concept VariantMember = requires(Var var) {
{safe_get<T>(var)};
};

(我添加并声明 1,这给了我“匹配且仅一次”)。

然后我们返回您的 S模板和everything works .

关于c++ - 导致 msvc 和 clang 中编译器错误的概念?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67470470/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com