是否有定义编译时类契约的模式?
我的目标是:
- 可维护性 - 在大型代码库中,指定和验证编译时契约非常有用,因此依赖性很明显。
- 质量错误消息 - 与其提示模板深处的一行代码无法调用方法,不如将契约(Contract)履行的缺失暴露出来。
类似...
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);
我会接受:
- 在编译时执行合约的方式
- 捕获/记录编译时合约的模式
- {静态方法、成员方法、typedef 等}子集的解决方案
- 重新定义我的问题陈述的解决方案
- 最佳实践
最佳答案
此时我首选的方法是借用 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 可用的。
关于C++ 编译时类契约(即模板元编程),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36752021/