【问题标题】:Curiously recurring template pattern with variadic templates (C++)带有可变参数模板的奇怪重复模板模式 (C++)
【发布时间】:2016-06-08 20:51:37
【问题描述】:

我有以下代码:

#include <iostream>

template <typename Derived>
struct Base {
    void print() const { static_cast<const Derived*>(this)->print(); }  
};

struct Value : public Base<Value> {
    int i;
    void print() const { std::cout << "Value: " << i << std::endl; }
    Value(int j) : i(j) {}
};

void do_variadic_thing() {}

template <typename Derived, typename... Args>
void do_variadic_thing(const Base<Derived>& b, Args... args) {
    std::cout << "Inside do_variadic_thing" << std::endl;
    b.print();
    do_variadic_thing(args...);
}

template <typename Derived>
void do_thing(const Base<Derived>& b) {
    std::cout << "Inside do_thing" << std::endl;
    b.print();
    do_variadic_thing(b, b, b);
}

int main(int argc, char** argv) {
    do_thing(Value(1));
}

这段代码使用奇怪重复的模板模式定义了一个编译时多态类,其方法名为print

我想要做的是从具有可变数量参数 (do_variadic_thing) 的函数中运行 print 方法。上面提供的代码可以编译,但会产生奇怪的输出:

Inside do_thing
Value: 1
Inside do_variadic_thing
Value: 1
Inside do_variadic_thing
Value: 4206337
Inside do_variadic_thing
Value: 4206337

我不明白为什么在do_variadic_thing 内的第二次递归调用之后打印的值会发生变化。参数b被复制了3次;它的类型也相同(即Base&lt;Value&gt;)。似乎不知何故,在第二次调用之后,参数不再引用一些有效的内存。

这怎么可能?

【问题讨论】:

    标签: c++ c++11 variadic-templates compile-time crtp


    【解决方案1】:

    通过引用传递:

    void do_variadic_thing(const Base<Derived>& b, const Args&... args)
                                                             ^
                                                             here
    

    【讨论】:

    • 谢谢。我错过了这样一个事实,即引用 b 实际上是作为可变参数部分的 副本 传递的。
    【解决方案2】:

    您正在传递第二个/第三个实例按值 - 考虑如何构造副本。

    【讨论】:

    • 还要注意Base&lt;Value&gt;不是Value,它不包含i字段(这个问题叫做“对象切片”)。
    【解决方案3】:

    变量b的类型是Base&lt;Value&gt; const&amp;,但它引用的对象是Value类型。当您复制 b 以将其复制到 do_thing 中时,您正在切片它;也就是说,只复制Base&lt;Value&gt; 部分。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-09-08
      • 1970-01-01
      • 2013-02-15
      • 2011-08-06
      • 2012-01-20
      • 2016-06-21
      • 1970-01-01
      相关资源
      最近更新 更多