c++ - 具有模板化类的通用引用

标签 c++ templates universal-reference

例子:

template <typename T>
class Bar
{
public:
    void foo(T&& arg)
    {
        std::forward<T>(arg);
    }
};

Bar<int> bar;    

bar.foo(10); // works

int a{ 10 };
bar.foo(a); // error C2664: cannot convert argument 1 from 'int' to 'int &&'

似乎通用引用适用于模板函数并且适用于类型推导,对吧?所以在类里面使用它没有意义吗?在我的情况下使用 std::forward 是否有意义?

最佳答案

请注意,首选术语(即将出现在规范的 future 版本中的术语)现在是转发引用

如您所说,转发引用仅适用于函数模板中的类型推导。在你的例子中,当你说 T&& 时,Tint。它不能是 int& 因为它已在您的 Bar 实例化中明确说明。因此,不会出现引用折叠规则,因此您无法进行完美转发。

如果你想在成员函数中做完美的转发,你需要有一个成员函数模板:

template <typename U>
void foo(U&& arg)
{
    std::forward<U>(arg); //actually do something here
}

如果您绝对需要 U 具有与 T 相同的非限定类型,您可以执行 static_assert:

template <typename U>
void foo(U&& arg)
{
    static_assert(std::is_same<std::decay_t<U>,std::decay_t<T>>::value, 
                  "U must be the same as T");
    std::forward<U>(arg); //actually do something here
}

std::decay 对您来说可能有点过于激进,因为它会将数组类型衰减为指针。如果这不是您想要的,您可以编写自己的简单特征:

template <typename T>
using remove_cv_ref = std::remove_cv_t<std::remove_reference_t<T>>;

template <typename T, typename U>
using is_equiv = std::is_same<remove_cv_ref<T>, remove_cv_ref<U>>;

如果你需要一个可变版本,我们可以写一个are_equiv trait。首先,我们需要一个特征来检查包中的所有特征是否为真。我将使用 bool_pack 方法:

namespace detail
{
    template<bool...> struct bool_pack;
    template<bool... bs>
    using all_true = std::is_same<bool_pack<bs..., true>, bool_pack<true, bs...>>;
}
template <typename... Ts>
using all_true = detail::all_true<Ts::value...>;

然后我们需要检查 Ts...Us... 中的每一对类型是否满足 is_equiv。我们不能将两个参数包作为模板参数,所以我将使用 std::tuple 来分隔它们(您可以使用哨兵节点,或者如果需要,可以在中途拆分包):

template <typename TTuple, typename UTuple>
struct are_equiv;

template <typename... Ts, typename... Us>
struct are_equiv <std::tuple<Ts...>, std::tuple<Us...>> : all_true<is_equiv<Ts,Us>...>
{};

然后我们可以这样使用:

static_assert(are_equiv<std::tuple<Ts...>,std::tuple<Us...>>::value, 
              "Us must be equivalent to Ts");

关于c++ - 具有模板化类的通用引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30569454/

相关文章:

c++ - 对要通过 winsock 发送的结构数组(指针?)进行类型转换

c++ - 重载 += 或 -= 运算符的好处

具有不可更改的通用引用函数模板的 C++ 重载解决方案

c++ - C++ 模板函数的行为

c++ - 多线程:apache 可移植运行时与 boost::thread?

c# - 设计用于通过TCP与Arduino通信的协议(protocol)

c++ - 没有优化的 g++ 4.9 上静态 constexpr 的 undefined reference

C++显式复制构造函数?

c++ - 在类中使用不同的模板参数

c++ - 默认模板类型可以作为通用引用吗?