2013-08-08 4 views
0

Рассмотрят следующий шаблон структуры:члены данных как именующая-ссылка или RValue-копий

template<typename T> 
struct X 
{ 
    X(T t) : t(std::forward<T>(t)) {} 

    T t; 
}; 

где Т будет либо именующей-ссылка (например, const int&) или регулярное значение (например, int). Идея состоит в том, чтобы использовать lvalue-reference всякий раз, когда X построен из lvalue и имеет постоянное значение при построении от rvalue.

Таким образом, следующие фабричные функции определены для создания экземпляра X с такими свойствами:

template<typename T> 
X<const T&> 
CreateX(const T& val) 
{ 
    return X<const T&>(val); 
} 

template<typename T> 
typename std::enable_if<std::is_rvalue_reference<T&&>::value, X<T>>::type 
CreateX(T&& val) 
{ 
    return X<T>(std::move(val)); 
} 

До сих пор, так хорошо. Если мы теперь рассмотрим шаблон структуры Y:

template<typename T, typename U> 
struct Y 
{ 
    Y(T t, U u) : t(std::forward<T>(t)), u(std::forward<T>(u)) {} 

    T t; 
    U u; 
}; 

, и мы решили сделать такую ​​же аналогию, как и раньше для X, мы в конечном итоге эти четыре заводских функций:

template<typename T, typename U> 
Y<const T&, const U&> 
CreateY(const T& t, const U& u) 
{ 
    return Y<const T&, const T&>(t, u); 
} 

template<typename T, typename U> 
typename std::enable_if<std::is_rvalue_reference<T&&>::value, Y<T, const U&>>::type 
CreateY(T&& t, const U& u) 
{ 
    return Y<T, const U&>(std::forward<T>(t), u); 
} 

template<typename T, typename U> 
typename std::enable_if<std::is_rvalue_reference<U&&>::value, Y<const T&, U>>::type 
CreateY(const T& t, U&& u) 
{ 
    return Y<const T&, U>(t, std::forward<T>(u)); 
} 

template<typename T, typename U> 
typename std::enable_if<std::is_rvalue_reference<T&&>::value and std::is_rvalue_reference<U&&>::value, Y<T, U>>::type 
CreateY(T&& t, U&& u) 
{ 
    return Y<T, U>(std::forward<T>(t), std::forward<T>(u)); 
} 

Есть альтернативный способ для получения того же результата, возможно, менее многословного? К счастью, моему приложению не потребуется более двух элементов данных шаблона, но потребуются несколько других классов, таких как Y, требующих четырех заводских функций для каждого из них.

+0

'шаблон Х make_X (Т && v) {возвращение Х {станд :: вперед (v)}; } ', нет глупых SFINAE. Это работает как для lvalues, так и для rvalues. Я бы сменил конструктор на 'T &&', поэтому у вас нет ненужного перехода от ctor-параметра к члену. – Xeo

+0

Благодаря @Xeo, но это приводит к неконстантным lvalue-ссылкам при построении из lvalues, и я хотел бы, чтобы они были константными ссылками lvalue. Я согласен с использованием 'T &&', чтобы избежать дополнительного перемещения. – Allan

+1

Затем сделайте просто свойство, которое преобразует 'T &' -> 'T const &'. Не должно быть трудно. – Xeo

ответ

4

это приводит к неконстантной Lvalue ссылок, когда строятся из lvalues, и я хотел бы, чтобы они были константным Lvalue ссылка

Вы можете написать простой признак, превращающие ссылки Lvalue:

template<class T> 
struct transform_parameter{ using type = T; }; 

template<class T> 
struct transform_parameter<T&>{ using type = T const&; }; 

template<class T> 
using TransformParameter = typename transform_parameter<T>::type; 

и применить это для всех соответствующих параметров шаблона:

template<class T> 
X<TransformParameter<T>> make_X(T&& v){ 
    return {std::forward<T>(v)}; 
} 

Я также использовал бит-init-list (aka равномерную инициализацию), чтобы сохранить меня от написания типа дважды.

+0

Спасибо @Xeo. Не то, чтобы ваше решение не было достаточно хорошим, но пытаясь исследовать более темные углы C++ 11, почему это не работает: 'template using TransformParameter = typename std :: условный :: value, T, typename std :: add_const :: type> '? – Allan

+0

@Allan: Если '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ' – Xeo

+0

Есть ли альтернатива, использующая 'std :: условный' и любые другие конструкции, доступные в стандартной библиотеке? – Allan

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

  • Нет связанных вопросов^_^