如何重载<<运算符使用模板函数向向量添加元素? (C ++)

时间:2018-05-08 20:20:57

标签: c++ templates vector operators overloading

我正在为学校做一个项目,我的老师要我们超载“<<”运算符,以便它向向量添加元素。他还希望我们使用模板,以便它可以用于任何类型的元素。

这是我的头文件代码:

template<typename T>
vector<T>& operator<<(vector<T>& v, const T element) {
    v.push_back(element);
    return v;
}

以下是我正在尝试运行的内容:

v1 << "Atlanta" << "Dallas" << "Chicago" << "Boston" << "Denver";

我得到的错误是:

error C2676: binary '<<': 'std::vector<std::string,std::allocator<_Ty>>' does not define this operator or a conversion to a type acceptable to the predefined operator

任何人都可以帮我解释为什么这不起作用?我正在使用最新版本的visual studio,我已将我的文件正确添加到解决方案和所有内容中。当我用“const string element”替换“const T element”一段时间时,它工作了一段时间,但是一旦我再次添加了实现,它就无法工作了。谢谢你的建议。

编辑:感谢您的帮助,以下是最终为我工作的答案:

template<typename T, typename U>
vector<T>& operator<<(vector<T>& v, const U& element) {
    v.push_back(element);
    return v;
}

4 个答案:

答案 0 :(得分:4)

"Atlanta"之类的字符串文字不是std::string类型(它们是char的数组),但是你的函数需要向量元素类型和运算符右手参数类型是同一类型。

如果允许右手参数类型不同,那么它可以工作,例如:

template<typename T, typename U>
std::vector<T>& operator<<(std::vector<T>& v, U&& element) {
    v.emplace_back(std::forward<U>(element));
    return v;
}

请注意,我将参数移动到矢量中以避免不必要的深层复制,例如, std::string按值传入。

修改已更改为使用emplace_back,如评论

中所述

答案 1 :(得分:4)

要添加到the solution by emlai,使用完美参数转发可能会更好:

template<typename T, typename U>
std::vector<T>& operator<<(std::vector<T>& v, U&& element) {
    v.emplace_back(std::forward<U>(element));
    return v;
}

与@emlai使用std::move的解决方案相比,这个使用完美的参数转发,它可以直接将对象移动到向量中,而不是按值传递。

编辑已更改为使用emplace_back,如评论

中所述

答案 2 :(得分:1)

使用时

v1 << "Atlanta" << "Dallas" << "Chicago" << "Boston" << "Denver";

参数T不会推断为std::string‘const char [8]推导出"Atlanta"。其他参数的类型将以类似方式推断出来。

更改函数,以便从std::vector推断出元素的类型。

template<typename Vector>
Vector& operator<<(Vector& v, typename Vector::value_type const& element) {
    v.push_back(element);
    return v;
}

答案 3 :(得分:0)

如果向量元素的类型和运算符的参数匹配,则会编译以下内容:

std::vector<const char*> v1;
v1 << "Atlanta" << "Dallas" << "Chicago" << "Boston" << "Denver";

同样地,使用std::string文字也适用于std::string s的向量:

using namespace std::string_literals;
std::vector<std::string> v1;
v1 << "Atlanta"s << "Dallas"s << "Chicago"s << "Boston"s << "Denver"s;

可以通过添加另一个模板将char数组直接放入std::string元素:

//this template will accept the const char array and construct a string
template<class T, class S,  size_t N>
std::vector<S>& operator<<(std::vector<S>& v, const T(& arr)[N]) 
{
    v.push_back({std::begin(arr), std::end(arr)});
    //v.push_back(arr); // would also work for char
    return v;
}