#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:二进制'&lt;&lt;' :没有找到哪个运算符采用'std :: vector&gt;'类型的左手操作数(或者没有可接受的转换)
为什么模板模板参数不能按预期工作?
答案 0 :(得分:6)
您的函数采用右值引用,但您传递左值 - 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;
}
这有效,但不会给我们任何简单的方法来支持收集价值。这里正确的解决方案IMO将停止使用模板模板,static_assert
表示容器value_type
匹配T
或SFINAE运营商离开时如果不是:
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;
}
或
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;
}
完成这项工作后,现在如果您决定要支持集合右值,那么这很简单;以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);
}
N.b。上述实现仅允许使用完全匹配到Coll::value_type
的运算符,但允许任何可以转换为 Coll::value_type
的任何内容都是明智的。 } - 要实现这一点,只需将std::is_same
替换为std::is_convertible
。