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

标签 c++ template-meta-programming compile-time

是否有定义编译时类契约的模式?

我的目标是:

  • 可维护性 - 在大型代码库中,指定和验证编译时契约非常有用,因此依赖性很明显。
  • 质量错误消息 - 与其提示模板深处的一行代码无法调用方法,不如将契约(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/

相关文章:

c++ 什么时候包含 cpp 即使我们有 .h 文件

c++ - 命名元组元素

regex - 如何正确设置正则表达式以用 perl 替换多行变量占位符

java - 如何在 java 的编译时检索 Long.MAX_VALUE 的字符串值?

c++ - 有没有办法将表从主机复制到设备(CUDA 和 C++)

c++ - 调用 `shared_ptr.get()` 与复制初始化,有什么区别?

c++ - 一些 const char * 在编译时不可用?

c++ - 将字符串文字传递给模板字符数组参数

c++ - 替换方法改变 QByteArray 的大小

c++ - 在编译时解包数组范围 (C++11/14)