用C++打字的静态鸭子

Mic*_*ael 8 c++ templates duck-typing static-polymorphism c++11

对于模板参数给出的类型,C++有一些鸭子类型.我们不知道什么类型DUCK1DUCK2将来,但只要他们可以quack(),它将编译和运行:

template <class DUCK1, class DUCK2>
void let_them_quack(DUCK1* donald, DUCK2* daisy){
  donald->quack();
  daisy->quack();
}
Run Code Online (Sandbox Code Playgroud)

但是写起来有点不方便.当我完全不关心什么实际类型DUCK1DUCK2有,而是要充分利用鸭打字的想法,那么我想有一些sligthly不同于上面:

  1. 我想省略编写一个重复且大多没有意义的模板参数列表(想象一下如果有7只鸭子会发生什么......)
  2. 我想更清楚地说明这些类型从未使用过,而且它只是重要的接口.
  3. 我想要一种界面注释/检查.以某种方式清楚该类型背后的接口.(然而,这与鸭子打字有点形成对比.)

C++是否提供任何功能来实现3个想法中的一个或多个?

(我知道虚拟继承在大多数情况下是实现这种模式的首选方法,但这里的问题是关于静态多态的情况.)

lis*_*rus 11

关于问题1和2:从C++ 14开始,你可以省略显式template <typename ...样板和使用auto,但只能在lambdas中使用:

auto let_them_quack = [] (auto & donald, auto & daisy){
    donald.quack();
    daisy.quack();
};
Run Code Online (Sandbox Code Playgroud)

(是的,我更喜欢对指针的引用).GCC允许在通常的功能中作为扩展.

对于问题3,你所谈论的是所谓的概念.它们在C++中存在了很长时间,但仅作为一个文档术语.现在,Concepts TS正在进行中,允许您编写类似的东西

template<typename T>
concept bool Quackable = requires(T a) {
    a.quack();
};

void let_them_quack (Quackable & donald, Quackable & daisy);
Run Code Online (Sandbox Code Playgroud)

请注意,它还不是C++,只是正在进行的技术规范.不过,GCC 6.1似乎已经支持它了.使用当前C++实现概念和约束是可能的; 你可以在boost中找到一个.

  • AFAIK你的顶级例子仅适用于lambda不是自由函数. (3认同)
  • 始终始终使用`-pedantic :)编译您的gcc代码 (2认同)

101*_*010 5

我想省略编写一个重复且大多没有意义的模板参数列表(想象一下如果有7只鸭子会发生什么......)

为此,您可以使用可变参数模板并执行以下操作:

template<typename DUCK>
void let_them_quack(DUCK &&d) {
  d.quack();
}

template<typename DUCK, typename... Args>
void let_them_quack(DUCK &&d, Args&& ...args) {
  d.quack();
  let_them_quack(std::forward<Args>(args)...);
}
Run Code Online (Sandbox Code Playgroud)

现场演示