检测运算符是否存在并且可以在c中调用(考虑static_asserts)

给定2种类型T和U我想检测是否可以在对象之间调用operator *(即可以写t * u,其中t是T类型而u是U类型)

我正在使用c++ detection idiom,但由于它在我的编译器中尚未提供,我自己就像这样实现了它

struct nonesuch {
    nonesuch() = delete;
    ~nonesuch() = delete;
    nonesuch(nonesuch const&) = delete;
    void operator=(nonesuch const&) = delete;
};

namespace detail {
template <class Default,class AlwaysVoid,template<class...> class Op,class... Args>
struct detector {
    using value_t = std::false_type;
    using type = Default;
};

template <class Default,class... Args>
struct detector<Default,std::void_t<Op<Args...>>,Op,Args...> {
    using value_t = std::true_type;
    using type = Op<Args...>;
};

} // namespace detail

template <template<class...> class Op,class... Args>
using is_detected = typename detail::detector<nonesuch,void,Args...>::value_t;

template< template<class...> class Op,class... Args >
constexpr bool is_detected_v = is_detected<Op,Args...>::value;

现在我有这样的帮手:

template <typename T,typename U>
using multiply = decltype(std::declval<T>() * std::declval<U>());

并检测我是否可以调用

bool can_multiply = is_detected_v<multiply,T,U>

它几乎没问题,例如按预期打印1,0

std::cout << is_detected_v<multiply,int,int> << std::endl;
std::cout << is_detected_v<multiply,std::vector<int>,std::vector<int>> << std::endl;

但现在我上课了

template<typename T>
class A {
};

template<typename T>
A<T> operator*(const A<T>&,const A<T>&) {
    static_assert(!std::is_same<bool,T>::value);
    return A<T>();
}

这里A< bool>不能乘以A< bool>但我的代码检测到它是可能的

std::cout << is_detected_v<multiply,A<bool>,A<bool>> << std::endl; // 1
A<bool>() * A<bool>(); // does't compile

所以,我的问题是,如何修复我的代码,以便在static_asserted出来时不检测方法?我想我可以用一些sfinae替换static_assert但我不想(因为我没有访问权限,除了static_asserts有更好的错误消息).

解决方法

So,my question is,how to fix my code to not detect methods when they static_asserted out?

你根本做不到.这只是static_assert的缺点之一 – 无法从外部验证操作的有效性.那是因为static_assert不会发生在operator *的实例化的“直接上下文”中,所以SFINAE不适用 – 它总是一个硬错误.

I suppose I can replace static_assert with some sfinae but I don’t want to (because I don’t have access and besides static_asserts have better error messages).

我同情.但这基本上是权衡取舍. SFINAE和类型检查,或static_assert和更清晰的错误. (当然在这种情况下你可以写一个非模板A< bool>运算符*(A< bool> const&,A< bool> const&)但这可能除此之外).

相关文章

/** C+⬑ * 默认成员函数 原来C++类中,有6个默认成员函数: 构造函数 析构函数 拷贝...
#pragma once // 1. 设计一个不能被拷贝的类/* 解析:拷贝只会放生在两个场景中:拷贝构造函数以及赋值运...
C类型转换 C语言:显式和隐式类型转换 隐式类型转化:编译器在编译阶段自动进行,能转就转,不能转就编译...
//异常的概念/*抛出异常后必须要捕获,否则终止程序(到最外层后会交给main管理,main的行为就是终止) try...
#pragma once /*Smart pointer 智能指针;灵巧指针 智能指针三大件//1.RAII//2.像指针一样使用//3.拷贝问...
目录&lt;future&gt;future模板类成员函数:promise类promise的使用例程:packaged_task模板类例程...