Gcc 检查给定的 class 是否有 operator+

Gcc check whether the given class has operator+

我在下面创建了一个代码来测试 2 类:

是否有 operator+ 重载
template<typename T, typename U>
struct _has_plus_hlp {
    template<typename X, typename Y>
    static std::true_type _check(X&, Y&, decltype(std::declval<X>() + std::declval<Y>()) = {});
    static std::false_type _check(...);

    using type = decltype(_check(std::declval<T>(), std::declval<U>()));
};
template<typename X, typename Y>
constexpr bool has_plus_v = _has_plus_hlp<X, Y>::type::value; 

int main()
{
    std::cout << std::boolalpha << detail::has_plus_v<int, std::string> << std::endl;
    auto f = [](auto& a, auto& b) {
        std::cout << std::boolalpha << detail::has_plus_v<decltype(a), decltype(b)> << std::endl;
    };
    std::string str = "HELLO";
    int num = 5;
    f(num, str);
}

这是我为 g++ (7.4.0) 得到的:

false
true

而我希望在 clang 的情况下两者都是假的:

false
false

我是不是搞错了什么?

您的原始版本不起作用,因为 std::declval<> returns r 值和常规引用无法绑定到它。解决方法是绑定到转发引用:

static std::true_type _check(X&&, Y&&, decltype(std::declval<X>() + std::declval<Y>()) = {});

稍微简单一点的版本:

template<class T, class U>
auto has_plus_test(T&& t, U&& u) -> decltype(static_cast<void>(t + u), std::true_type{});

std::false_type has_plus_test(...);

template<class T, class U>
using has_plus = decltype(has_plus_test(std::declval<T>(), std::declval<U>()));

template<class T, class U>
constexpr bool has_plus_v = has_plus<T, U>::value;

int main() {
    std::cout << std::boolalpha << has_plus_v<int, int> << '\n'; // Outputs true.
    std::cout << std::boolalpha << has_plus_v<int, std::string> << '\n'; // Outputs false.
    std::cout << std::boolalpha << has_plus_v<std::string, std::string> << '\n'; // Outputs true.
}