«Шаблон typedef» внутри конструктора копирования не работает - PullRequest
1 голос
/ 17 марта 2011

Краткая справка: я пишу интеллектуальный указатель на основе политики (например, SmartPtr в библиотеке Loki), который может иметь разрушительную семантику копирования, такую ​​как 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!
}

1 Ответ

3 голосов
/ 17 марта 2011

Возможно, что-то подобное может сработать для вас. Я использовал std :: enable_if из C ++ 0x. С таким же успехом вы можете использовать бусты или свернуть свои собственные (это всего лишь пара строк кода).

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

Я не уверен, что это оптимально. Это был просто выстрел из бедра, одна из целей - минимальное расстояние от того места, куда вы направлялись. Возможно, это именно то место, куда вы хотите пойти, или, возможно, это просто поможет вам начать в правильном направлении.

...