2015-02-26 3 views
1

Я пытаюсь реализовать класс вариант, но у меня возникают проблемы с рекурсивной функцией C++:реализация Variant (VARIADIC шаблон)

template<typename Visitor, typename... Types> 
class VariantVisitor; 

template<typename... Types> 
class Variant 
{ 
    template <typename V, typename... types> 
    friend class VariantVisitor; 
public: 
    struct holder 
    { 
     virtual ~holder() {} 
    }; 

    template <typename T> 
    struct impl : public holder 
    { 
     impl(const T& t) : val(t) {} 
     T get() const { return val; } 
     T val; 
    }; 

    Variant() : mHolder(nullptr) {} 

    template <typename T> 
    Variant(const T& t) 
    { 
     mHolder = new impl<T>(t); 
    } 

    Variant(const Variant<Types...>& v) : mHolder(nullptr) 
    { 
     copy<Types...>(v); 
    } 

    ~Variant() 
    { 
     delete mHolder; 
    } 

    template <typename T> 
    Variant<Types...>& operator = (const T& t) 
    { 
     if (!mHolder) { 
      mHolder = new impl<T>(t); 
      return *this; 
     } 

     _ASSERT(typeid(*mHolder) == typeid(impl<T>)); 
     static_cast<impl<T>*>(mHolder)->val = t; 
     return *this; 
    } 

    Variant<Types...> &operator = (const Variant& v) 
    { 
     copy<Types...>(v); 
     return *this; 
    } 

    template <typename T> 
    T Get() const 
    { 
     _ASSERT(mHolder && typeid(*mHolder) == typeid(impl<T>)); 
     return static_cast<impl<T>*>(mHolder)->get(); 
    } 

    template<typename T> 
    bool Is() const 
    { 
     return (mHolder && typeid(*mHolder) == typeid(impl<T>)); 
    } 
private: 
    template <typename T> 
    void copy(const Variant<Types...>& v) 
    { 
     if (mHolder) delete mHolder; 
     impl<T>* ptr = static_cast<impl<T>*>(v.mHolder); 
     mHolder = new impl<T>(*ptr); 
    } 

    template <typename T, typename...types> 
    void copy(const Variant<Types...>& v) 
    { 
     if (!Is<T>()) 
      return copy<types...>(v); 

     copy<T>(v); 
    } 

    holder* mHolder; 
}; 

Visual C++ 2013 говорит, что неоднозначный вызов этой линии :

copy<T>(v); 

Я новичок в шаблоны переменного числа, но я думаю, что следует различать две функцию копирования для числа типов, не так ли? Так почему они могут быть как перегрузками? И, конечно, как я могу это исправить?

+0

'std :: unique_ptr mHolder;' – Casey

ответ

2

Пакеты параметров могут быть пустыми. В результате компилятор не может отличить

template <typename T> void copy(const Variant& v); // with T = T 

и

template <typename T, typename...types> 
void copy(const Variant& v); // with T = T, types = empty pack 

Исправление сделать вторую версию матч только два или более аргументов шаблона:

template <typename T, typename T2, typename...types> 
void copy(const Variant& v); 

тело необходимо будет обновить, чтобы использовать copy<T2, types...>(v). Обратите внимание, что в определении класса Variant вы можете просто написать Variant, и это будет означать Variant<Types...>.

Смежные вопросы