2016-07-28 2 views
0

Возьмите следующий,заставляя Шаблонный конструктор над компилятором копиеем конструктора

template<class T> 
struct Foo { 
    Foo(){} 

    // a template constructor "generalized" over related types 
    template<class U> 
    Foo(Foo<U> const&) { 
     std::cout << 1; 
    } 

    // copy constructor 
    Foo(Foo const&) { 
     std::cout << 2; 
    } 
}; 

и его пользователь:

void main() { 
    Foo<int> f1; 
    Foo<const int> f2(f1); // prints 1 
    Foo<const int> f3(f2); // prints 2 
} 

Даже без явного копирующего конструктора, компилятор генерирует один и использует для f3(f2).

Есть ли способ заставить шаблон перегружать? Например, может ли конструктор копирования быть SFINAE'd? Это делается для того, чтобы избежать дублирования кода, поскольку, как ни удивительно, не представляется возможным использовать делегирующие конструкторы (делегирование от конструктора копирования к шаблону).

+0

Неа, это не то же самое, и это делает 'f3 (f2)' ошибка, так как разрешение перегрузки по-прежнему выбирает конструктор копирования и ошибок, как 'delete'd. (комментарий, на который я ответил, спрашивал, есть ли опция 'delete') – sly

ответ

5

Шаблон конструктора никогда не может быть конструктором копирования, поэтому, если вы его не определяете, компилятор будет неявно делать это за вас, как вы узнали.

Одним из способов избежать дублирования кода является определение третьего конструктора и его делегирование от обоих ваших конструкторов, показанных выше.

template<class T> 
struct Foo { 
    Foo(){} 

    struct tag{}; 

    // a template constructor "generalized" over related types 
    template<class U> 
    Foo(Foo<U> const& f) 
    : Foo(tag{}, f) 
    { 
     std::cout << 1 << '\n'; 
    } 

    // copy constructor 
    Foo(Foo const& f) 
    : Foo(tag{}, f) 
    { 
     std::cout << 2 << '\n'; 
    } 

private: 
    template<class U> 
    Foo(tag, Foo<U> const&) 
    { 
     std::cout << 3 << '\n'; 
    } 
}; 

Live demo

+0

интересное предложение. фактически решает практический пример использования. однако, не является прямым ответом на вопрос «может ли конструктор копирования быть отключен» (искал неявную версию с аргументом sfinaed по умолчанию и т. д. - возможно, ответ отрицательный). Будучи спорным в этот момент, я думаю .... – sly

+2

@lyly Я не вижу, как вы можете SFINAE-отключить конструктор копирования. Это не шаблон, поэтому нет никакого удержания, которое необходимо для SFINAE. – Praetorian

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