C++ 编译时 class 契约(即模板元编程)

C++ compile-time class contracts (ie, template-metaprogramming)

是否有用于定义编译时 class 契约的任何模式?

我的目标是:

类似...

class StaticContract {
  static void Method();
};

class MeetsContract {
  static void Method();
};

// T must have all methods of StaticContract, or compile-time error.
template <class T /*   : StaticContract   */>
void DoSomething(T t);

我会接受:

这个技巧似乎提供了面包屑(来自 detecting typedef at compile time (template metaprogramming)

template<typename T>
struct void_ { typedef void type; };

template<typename T, typename = void>
struct Foo {};

template<typename T>
struct Foo <T, typename void_<typename T::const_iterator>::type> {
      void do_stuff(){ ... }
};

嗯,如何将其编织成可行的模式?

此时我的首选方法是借用 Yakk 的 can_apply 元函数:

namespace details {
    template <class...>
    using void_t = void;    

    template <template <class...> class Z, class, class...>
    struct can_apply : std::false_type {};

    template <template <class...> class Z, class...Ts>
    struct can_apply<Z, void_t<Z<Ts...>>, Ts...> : std::true_type{};
}

template <template <class...> class Z, class...Ts>
using can_apply = details::can_apply<Z, void, Ts...>;

把它贴在某个地方以便妥善保管。然后,我们可以将类型的契约定义为我们期望有效的表达式。在这种情况下,我们需要一个名为 Method:

的非 const 成员函数
template <class T>
using StaticContract = decltype(std::declval<T&>().Method());

那么我们只需要它:

template <class T>
void DoSomething(T ) {
    static_assert(can_apply<StaticContract, T>::value, "!");
}

合同也可以任意复杂。也许你需要 T 也可以复制分配和递增:

template <class T>
using StaticContract = decltype(
    std::declval<T&>().Method(),
    std::declval<T&>() = std::declval<T const&>(),
    ++std::declval<T&>()
    );

如果您选择该方法而不是 static_assert 方法,那么这也自然适用于 SFINAE。