我的 SFINAE 出了啥问题?:测试支持的运算符
Posted
技术标签:
【中文标题】我的 SFINAE 出了啥问题?:测试支持的运算符【英文标题】:What's wrong with my SFINAE?: Testing Supported Operators我的 SFINAE 出了什么问题?:测试支持的运算符 【发布时间】:2019-10-26 07:20:06 【问题描述】:这是有问题的代码:
template <typename=std::enable_if_t<supports_v<std::equal_to<>, T>> >
bool alreadyValue(const T &value) return this->value == value;
// alternate case if T does not support equals operator
bool alreadyValue(const T &value) return false;
这是我的支持定义:
template<typename F, typename... T, typename = decltype(std::declval<F>()(std::declval<T>()...))>
std::true_type supports_test(const F&, const T&...);
std::false_type supports_test(...);
template<typename> struct supports;
template<typename F, typename... T> struct supports<F(T...)>
: decltype(supports_test(std::declval<F>(), std::declval<T>()...));
template<typename F, typename T>
constexpr bool supports_v = supports<F(T, T)>::value;
template<typename F, typename... T>
constexpr bool all_supports_v = (supports<F(T, T)>::value && ...);
现在,MSVC 19.20 对这段代码没有任何问题。
但 GCC 9.1 抱怨:
使用 enable_if_t = typename std::enable_if::type [with bool _Cond = supports_v<:equal_to>, A> 替换 'template
; _Tp = void]': 错误:'struct std::enable_if
'中没有名为'type'的类型
由于 SFINAE 知道“结构中没有类型”应该静默失败,因为它不是错误,所以我的问题是我做错了什么吗?
这是我正在使用的示例:
(GCC 9.1)https://godbolt.org/z/LNfjyp (MSVC 19.20)https://godbolt.org/z/wJqXFq【问题讨论】:
你能提供一个minimal reproducible example吗?像第二个alreadyValue
重载大概应该是一个模板,等等。
我建议在这种情况下使用if constexpr
。更容易阅读。见***.com/a/51659883/2466431
@JVApen,谢谢,我从来不知道我可以像这样内联一个 constexpr。
对于 SFINAE,您需要未评估的上下文和依赖类型。你似乎两者都没有。你想要完成什么?至于为什么 MSVC 接受这个。好吧,它只是不是一个很好的 C++ 编译器。尤其是如果你去做这些事情。
就目前而言,T 是类的模板参数,而不是方法(显然)。这可能与以下question有关。
【参考方案1】:
正如@rubenvb 和@Mike Spencer 所暗示的那样, enable_if 不在未评估的上下文中,因为没有依赖于函数的泛型类型。所以没有 SFINAE。
作为一种解决方案,我改为将该函数构建为通用支持函数:
template<typename T, bool=supports_v<std::equal_to<>, T>>
struct is_equal_t;
template<typename T>
struct is_equal_t<T, true>
bool operator() (const T& x, const T& y) const return x==y;
;
template<typename T>
struct is_equal_t<T, false>
bool operator() (const T& x, const T& y) const return false;
;
template<typename T>
bool is_equal(const T& x, const T& y)
static is_equal_t<T> cmp;
return cmp(x, y);
【讨论】:
以上是关于我的 SFINAE 出了啥问题?:测试支持的运算符的主要内容,如果未能解决你的问题,请参考以下文章