06 September 2023

C++ 核心指南目录

“Avoid complementary constraints”

理由

清晰。可读性好。通过互补约束表达的相反的要求很容易弄错。

例子

一开始,人们尝试通过互补要求来定义函数。

template<typename T>
    requires !C<T>    // bad
void f();

template<typename T>
    requires C<T>
void f();

其实这样写会更好:

template<typename T>   // general template
    void f();

template<typename T>   // specialization by concept
    requires C<T>
void f();

如果限制条件 C<T> 不满足要求,编译器会选择没有限制的那个模板。如果你不像或无法定义不受限制的版本的 f() ,你可以删除它。

template<typename T>
void f() = delete;

编译器会选择重载的版本,或者抛出一个恰当的错误。

注意

互补限制条件在用到 enable_if 的代码里很常见。

template<typename T>
enable_if<!C<T>, void>   // bad
f();

template<typename T>
enable_if<C<T>, void>
f();

注意

针对某个单一的要求,大家似乎认为互补要求是可以管理好的。其实,对于 2 个以上的需求,需要的定义数量指数级增长。

C1<T> && C2<T>
!C1<T> && C2<T>
C1<T> && !C2<T>
!C1<T> && !C2<T>

这样,出错的概率也不断增长。

强化

  • 标记函数中出现互补对的限制条件的情况 C<T>C<T>