xml*_*lmx 0 c++ templates compiler-errors c++11
#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);
}
Run Code Online (Sandbox Code Playgroud)
VS 2015年产量:
错误C2678:二进制'<<':找不到运算符,它采用类型'std :: vector>'的左手操作数(或者没有可接受的转换)
为什么模板模板参数不能按预期工作?
你的函数接受一个右值引用,但你传递一个左- Left<T, Alloc>&&是不是转发引用,所以用它当作这样std::forward等是不正确的.现在我们将禁止收集rvalues来简化事情:
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;
}
Run Code Online (Sandbox Code Playgroud)
以上是更接近一步,但如果传递左值,将无法工作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;
}
Run Code Online (Sandbox Code Playgroud)
这有效,但不会给我们任何简单的方法来支持集合rvalues.这里正确的解决方案是IMO要停止使用模板模板,要么static_assert是容器的value_type匹配,要么是TSFINAE,如果不是:
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;
}
Run Code Online (Sandbox Code Playgroud)
要么
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;
}
Run Code Online (Sandbox Code Playgroud)
完成后,现在如果您决定要支持集合右值,那么这很简单; 以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);
}
Run Code Online (Sandbox Code Playgroud)
铌上面的实现只允许使用与运营商的精确匹配到Coll::value_type,但它可能是明智的,允许任何可以被转换成 Coll::value_type -实现这一点,只需更换std::is_same用std::is_convertible.