Can Boost声明方法调用实例化不会编译?

时间:2017-01-12 17:12:27

标签: c++11 boost instantiation assert template-meta-programming

以下代码运行正常,我对我强大的课程感到满意。

但是,断言某些方法调用实例化在编译时不能通过手动注释进行编译,这是非常繁琐的。我知道预见到编译将会中断只能通过实际编译来实现。这是一个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;
}

1 个答案:

答案 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类似,但不完全相同。