C++ 作为左值引用或右值副本的数据成员

C++ 作为左值引用或右值副本的数据成员,c++,templates,c++11,perfect-forwarding,C++,Templates,C++11,Perfect Forwarding,考虑以下结构模板: template<typename T> struct X { X(T t) : t(std::forward<T>(t)) {} T t; }; 到目前为止,一切顺利。如果现在考虑结构模板 y>代码>: template<typename T, typename U> struct Y { Y(T t, U u) : t(std::forward<T>(t)), u(std::forward<

考虑以下结构模板:

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

    T t;
};
到目前为止,一切顺利。如果现在考虑结构模板<代码> 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;
};
是否有其他方法可以获得相同的结果,也许不那么冗长?幸运的是,我的应用程序不需要两个以上的模板数据成员,但需要几个其他类,如
Y
,每个类需要四个工厂函数

当从左值构造时,这会导致非常量左值引用,我希望它们是常量左值引用

您可以编写一个转换左值引用的简单特征:

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;
模板
结构转换_参数{using type=T;};
模板
结构转换_参数{using type=T const&;};
模板
使用TransformParameter=typename转换_参数::type;
并将其应用于所有相关模板参数:

template<class T>
X<TransformParameter<T>> make_X(T&& v){
  return {std::forward<T>(v)};
}
模板
X制作X(T&v){
返回{std::forward(v)};
}
在这里,我还使用了一个大括号的init列表(也称为统一初始化)来避免我写两次类型

当从左值构造时,这会导致非常量左值引用,我希望它们是常量左值引用

您可以编写一个转换左值引用的简单特征:

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;
模板
结构转换_参数{using type=T;};
模板
结构转换_参数{using type=T const&;};
模板
使用TransformParameter=typename转换_参数::type;
并将其应用于所有相关模板参数:

template<class T>
X<TransformParameter<T>> make_X(T&& v){
  return {std::forward<T>(v)};
}
模板
X制作X(T&v){
返回{std::forward(v)};
}

在这里,我还使用了一个带括号的init列表(也称为统一初始化)来避免我写两次类型。

template X make_X(T&&v){return X{std::forward(v)};}
,不需要愚蠢的SFINAE。这适用于左值和右值。不过,我会将构造函数更改为采用
T&
,这样您就不会不必要地从ctor参数移动到member。谢谢@Xeo,但这会导致从左值构造非常量左值引用,我希望它们是常量左值引用。我同意使用
T&&
来避免额外的移动。然后做一个简单的特征,转换
T&
->
T常量&
。这应该不难。我认为如果你能用你的想法和转变特点写一个例子,对我和其他人将来都会有好处。再次感谢。
template X make_X(T&v){return X{std::forward(v)};}
,无需任何愚蠢的SFINAE。这适用于左值和右值。不过,我会将构造函数更改为采用
T&
,这样您就不会不必要地从ctor参数移动到member。谢谢@Xeo,但这会导致从左值构造非常量左值引用,我希望它们是常量左值引用。我同意使用
T&&
来避免额外的移动。然后做一个简单的特征,转换
T&
->
T常量&
。这应该不难。我认为如果你能用你的想法和转变特点写一个例子,对我和其他人将来都会有好处。再次感谢。谢谢@Xeo。并不是说你的解决方案不够好,而是试图探索更多C++11的黑暗角落,为什么这不起作用:
模板使用TransformParameter=typename std::conditional
?@Allan:例如,如果
t
X&
,那么
添加常量将导致
X&const
,既然你不能限定引用,它就被删除了。有没有其他方法可以使用标准库中可用的
std::conditional
和任何其他构造?@Allan:是的,但有点冗长:
typename std::conditional::type
,基本上先删除引用,然后添加
const
并返回引用?它是等效的吗?我总算让它工作起来了。谢谢@Xeo。并不是说你的解决方案不够好,而是试图探索更多C++11的黑暗角落,为什么这不起作用:
模板使用TransformParameter=typename std::conditional
?@Allan:例如,如果
t
X&
,那么
添加常量将导致
X&const
,既然你不能限定引用,它就被删除了。有没有其他方法可以使用标准库中可用的
std::conditional
和任何其他构造?@Allan:是的,但有点冗长:
typename std::conditional::type
,基本上先删除引用,然后添加
const
并返回引用?它是等效的吗?我设法让它工作起来了。