1

一些背景:我正在编写一个基于策略的智能指针(如Loki库中的SmartPtr),它可以具有像auto_ptr这样的破坏性复制语义。因此,它需要有一个模板拷贝构造函数来取得非const引用来修改被拷贝的对象。复制构造函数中的“Template typedef”不起作用

我想要做的是参数化复制构造函数通过策略中的某个变量的参数的常量,以便在不希望使用破坏性复制语义时使其成为常量。下面是我想到的简化代码,但不幸的是,它不起作用,因为编译器无法推导出模板参数。我有没有其他技术可以用来实现所需的行为?

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! 
} 
+0

你有一个“非推断的上下文”的问题,类似于这里 。问题在于编译器无法确定T2,而没有为所有**可能的类型实例化CopyArg并比较它们的嵌套类型。 – 2011-03-16 22:40:02

回答

3

也许像这样的东西可能适合你。我从C++ 0x中使用了std :: enable_if。你可以轻松使用boost,或者自己推出(这只是几行代码)。

#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! 
} 

我不是积极的,这是最佳的。这只是从臀部开始拍摄的,其中一个目标与您前往的地方距离最短。也许这就是你想要去的地方,或者这可能会让你开始朝着正确的方向前进。

+0

谢谢你的提示!尽管这个技巧看起来有点“脏”,因为在堆栈上创建了附加的虚拟变量。但是,我不认为有任何可能避免它。 – lizarisk 2011-03-17 17:38:53

+0

在C++ 0x中,您可以将“限制”添加为默认的模板参数,而不是默认的函数参数。我更喜欢风格上的默认模板参数。但我的编译器警告说这是一个C++ 0x功能。 – 2011-03-17 18:31:51