使用概念具有特定值类型的任何容器的 C++ 迭代器

Kel*_*áté 11 c++ sfinae enable-if c++-concepts c++20

我想摆脱enable_if模板中的所有邪恶s 并用 C++20 概念替换它们,但是几乎没有关于概念的任何信息,并且几乎我阅读的任何来源的语法都发生了变化。

这是一个函数,它接受任何带有MyClass值的容器的两个迭代器:

template <class IteratorType, typename = std::enable_if<std::is_same<
                                typename std::iterator_traits<IteratorType>::value_type,
                                MyClass
                            >::value, void>>
void myFunction( IteratorType begin, IteratorType end ) {}
Run Code Online (Sandbox Code Playgroud)

我知道可以使用概念转换此功能,但我找不到好的线索开始。

Sto*_*ica 5

可能不是最容易理解的参考,但概念的规范信息来源是可用的标准草案。其中概念定义在语法上指定为

1概念是定义对其模板参数的约束的模板。

concept-definition:
  concept concept-name = constraint-expression ;
concept-name:
  identifier
Run Code Online (Sandbox Code Playgroud)

它几乎就像一个 bool 变量模板常量,但它是用概念关键字定义的。所以将你的条件直接转化为一个概念本质上是这样的

template<typename T>
concept MyClassIter = std::is_same_v<
                        MyClass, 
                        typename std::iterator_traits<T>::value_type
                      >;
Run Code Online (Sandbox Code Playgroud)

有了这个概念,我们可以将其用作模板类型参数的类型约束,从而将您的模板转换为

template <MyClassIter IteratorType>
void myFunction( IteratorType begin, IteratorType end ) {}
Run Code Online (Sandbox Code Playgroud)

如果某个类型不满足约束,则丢弃此重载。在此上下文中不满意还包括替换失败。所以这和你最初的情况是一样的。

活生生的例子


Mik*_*her 5

最直接的翻译是

template <typename IteratorType>
requires std::same_as<typename std::iterator_traits<IteratorType>::value_type, MyClass>
void myFunction(IteratorType begin, IteratorType end) {}
Run Code Online (Sandbox Code Playgroud)

看:

上帝螺栓示例


L. *_* F. 5

为了适应 C++20 Ranges 生态系统:

template <std::input_iterator I, std::sentinel_for<I> S>
    requires std::same_as<std::iter_value_t<I>, MyClass>
constexpr void myFunction(I begin, S end)
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)