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