【问题标题】:"Template typedef" inside a copy constructor doesn't work复制构造函数中的“模板 typedef”不起作用
【发布时间】:2011-07-17 00:00:26
【问题描述】:

一些背景知识:我正在编写一个基于策略的智能指针(如 Loki 库中的 SmartPtr),它可能具有破坏性复制语义,如 auto_ptr。因此,它需要有一个模板复制构造函数采用非常量引用来修改被复制的对象。

我正在尝试做的是通过策略中的某个变量参数化复制构造函数所采用的参数的常量,以便在不需要破坏性复制语义时使其变为常量。这是我提出的想法的简化代码,但不幸的是,它不起作用,因为编译器无法推断模板参数。是否有任何其他技术可用于实现所需的行为?

template <typename T, bool isEnabled> struct AddConst {
    typedef T Type;
};

template <typename T> struct AddConst<T, true> {
    typedef const T Type;
};

struct MyCopyPolicy {
    static const bool kIsCopyArgConst = true;
};

template <typename T, class CopyPolicy> struct Foo {

    // A helper struct to achieve "template typedef".
    template <typename T2> struct CopyArg {
        typedef typename AddConst<Foo<T2, CopyPolicy>,
            CopyPolicy::kIsCopyArgConst>::Type Type;
    };

    Foo() {}
    // Template copy constructor. Doesn't work.
    template <typename T2> Foo(typename CopyArg<T2>::Type& rhs) {}
};

int main() {
    Foo<int, MyCopyPolicy> foo1;
    Foo<double, MyCopyPolicy> foo2 = foo1;  // error!
}

【问题讨论】:

  • 你有一个“非推断上下文”的问题,类似于这里 stackoverflow.com/questions/1268504/…>。问题是编译器如果不为 所有 可能的类型实例化 CopyArg 并比较它们的嵌套类型,就无法确定 T2。

标签: c++ templates metaprogramming smart-pointers copy-constructor


【解决方案1】:

也许这样的事情可能对你有用。我使用了 C++0x 中的 std::enable_if 。你可以很容易地使用 boost's,或者自己动手(只需要几行代码)。

#include <type_traits>

struct MyCopyPolicy {
    static const bool kIsCopyArgConst = true;
};

template <typename T, class CopyPolicy> struct Foo {

    // A helper struct to achieve "template typedef".
    template <typename T2> struct CopyArg {
        typedef CopyPolicy Type;
    };

    Foo() {}

    template <typename T2>
        Foo(const T2& rhs,
                typename std::enable_if<CopyArg<T2>::Type::kIsCopyArgConst>::type* = 0)
            {}
    template <typename T2>
        Foo(T2& rhs,
               typename std::enable_if<!CopyArg<T2>::Type::kIsCopyArgConst>::type* = 0)
            {}
};

int main() {
    Foo<int, MyCopyPolicy> foo1;
    Foo<double, MyCopyPolicy> foo2 = foo1;  // ok!
}

我不肯定这是最优的。这只是从臀部射击,其中一个目标是与您前进的位置保持最小距离。也许这就是你想去的地方,或者这会让你朝着正确的方向开始。

【讨论】:

  • 感谢您的精彩提示!虽然这个技巧看起来有点“脏”,因为在堆栈上创建了额外的虚拟变量。但是,我认为没有任何避免它的可能性。
  • 在 C++0x 中,您可以将“限制”添加为默认模板参数,而不是作为默认函数参数。我在风格上更喜欢默认的模板参数。但我的编译器警告说这是一个 c++0x 功能。
猜你喜欢
  • 2021-12-08
  • 1970-01-01
  • 2018-07-17
  • 2011-05-24
  • 1970-01-01
  • 2016-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多