gpt4 book ai didi

c++ - 为什么模板模板参数没有按预期工作?

转载 作者:太空宇宙 更新时间:2023-11-04 15:34:30 25 4
gpt4 key购买 nike

#include <vector>

template
<
typename T,
typename Alloc,
template<typename, typename> class Left
>
Left<T, Alloc>&&
operator <<(Left<T, Alloc>&& coll, T&& value)
{
coll.push_back(std::forward<T>(value));
return std::forward<Left<T, Alloc>>(coll);
}

using namespace std;

int main()
{
vector<int> c1;
c1 << int(8);
}

VS 2015 年产出:

错误 C2678:二进制“<<”:未找到接受类型为“std::vector>”的左手操作数的运算符(或没有可接受的转换)

为什么模板模板参数没有按预期工作?

最佳答案

您的函数采用右值引用,但您传递的是左值 – Left<T, Alloc>&& 不是 转发引用,因此用 std::forward 将其视为转发引用等是不正确的。现在我们将禁止集合右值来简化事情:

template<
typename T,
typename Alloc,
template<typename, typename> class Left
>
Left<T, Alloc>& operator <<(Left<T, Alloc>& coll, T&& value) {
coll.push_back(std::forward<T>(value));
return coll;
}

上面更近了一步,但是will not work如果为 value 传递了一个左值.一种选择是为 Left 强制使用正确的参数:

template<
typename T,
typename Alloc,
template<typename, typename> class Left
>
Left<typename std::decay<T>::type, Alloc>&
operator <<(Left<typename std::decay<T>::type, Alloc>& coll, T&& value) {
coll.push_back(std::forward<T>(value));
return coll;
}

Online Demo

这可行,但没有给我们留下任何支持集合右值的简单方法。 IMO 的正确解决方案是停止使用模板模板和 static_assert容器的 value_type火柴T或 SFINAE 运算符(operator)离开,如果没有:

template<typename Coll, typename T>
Coll& operator <<(Coll& coll, T&& value) {
static_assert(std::is_same<
typename std::decay<T>::type,
typename Coll::value_type
>::value,
"T does not match Coll::value_type"
);
coll.push_back(std::forward<T>(value));
return coll;
}

Online Demo

template<typename Coll, typename T>
typename std::enable_if<std::is_same<
typename std::decay<T>::type,
typename Coll::value_type
>::value,
Coll&
>::type
operator <<(Coll& coll, T&& value) {
coll.push_back(std::forward<T>(value));
return coll;
}

Online Demo

完成后,现在如果您决定要支持集合右值,这很容易完成;使用static_assert实现为例:

template<typename Coll, typename T>
Coll&& operator <<(Coll&& coll, T&& value) {
static_assert(std::is_same<
typename std::decay<T>::type,
typename std::decay<Coll>::type::value_type
>::value,
"T does not match Coll::value_type"
);
coll.push_back(std::forward<T>(value));
return std::forward<Coll>(coll);
}

Online Demo

注意上面的实现只允许使用运算符完全匹配Coll::value_type , 但允许任何可以转换为 Coll::value_type 的东西可能是明智的– 要实现这一点,只需替换 std::is_same std::is_convertible .

关于c++ - 为什么模板模板参数没有按预期工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38407898/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com