以下代码运行正常,我对我强大的课程感到满意。
但是,断言某些方法调用实例化在编译时不能通过手动注释进行编译,这是非常繁琐的。我知道预见到编译将会中断只能通过实际编译来实现。这是一个catch22的情况。但是,有没有一些漂亮的方式绕过它没有太多的代码混淆?
Boost是否有提供的东西?
#include <tchar.h>
#include <type_traits>
template<int SOMEMEANINGFULNUMBER>
class RobustClass {
private:
RobustClass() {}
public:
static RobustClass<SOMEMEANINGFULNUMBER> instance;
template <int I = SOMEMEANINGFULNUMBER>
typename std::enable_if<(I != 2) && (I == SOMEMEANINGFULNUMBER)>::type
doSomething() {
// Do something smart and useful!
}
};
template<int SOMEMEANINGFULNUMBER>
RobustClass<SOMEMEANINGFULNUMBER> RobustClass<SOMEMEANINGFULNUMBER>::instance;
typedef RobustClass<0> RobustClass0;
typedef RobustClass<2> RobustClass2;
int _tmain(int argc, _TCHAR* argv[])
{
RobustClass<0> robustClass0 = RobustClass0::instance;
RobustClass<2> robustClass2 = RobustClass2::instance;
robustClass0.doSomething(); // Compiles and runs fine
// robustClass2.doSomething(); // Beautifully breaks compilation.
// But I want to wrap this call so
// that it does NOT break the compilation.
// May be a catch22 wish, however.
return 0;
}
答案 0 :(得分:2)
我相信您希望能够检查无法从RobustClass<2>::doSomething()
类型的实例调用RobustClass<2>
。
目前,您通过强制构建中断,然后将其注释掉来检查这一点。这很烦人,因为每次检查都需要手动编辑代码。
我们可以使用SFINAE检测.doSomething()
对T
类型是否有效,然后按如下方式反转测试:
namespace details {
template<template<class...>class Z, class, class...Ts>
struct can_apply:std::false_type{};
template<template<class...>class Z, class...Ts>
struct can_apply<Z, std::void_t<Z<Ts...>>, Ts...>:std::true_type{};
}
template<template<class...>class Z, class...Ts>
using can_apply = details::can_apply<Z, void, Ts...>;
template<class X>
using do_something_r = decltype( std::declval<X>().doSomething() );
template<class X>
using can_do_something = can_apply<do_something_r, X>;
这会检测X
是否为doSomething
的有效类型。
您可以像这样使用测试:
static_assert( !can_do_something<RobustClass<2>&>{}, "doSomething should be disabled" );
can_apply
与提议的C ++ 20 is_detected
类似,但不完全相同。