-3

i tried the following code i found on the net and is perfectly working.

template<typename T,typename T2>
std::vector<T>& operator<<(std::vector<T>& v1, T2 t1){
v1.push_back(T(t1));
return v1;
 } 

but for me the argument t1 must be from type T and not T2. so my first question is: why when i do

std::vector<T>& operator<<(std::vector<T>& v1, ***T t1***) //instead of T2 t1

i have the following error: error: no match for 'operator<<' (operand types are 'std::vector >' and 'std::string {aka std::basic_string}')

my second question is a ligne 4 of the code: what does mean T(t1) ?

thanks a lot !

EDIT:

thanks for all your answers!

this is the code i was using to test and try to inderstand the function.

using namespace std; 

template<typename T>
std::vector<T>& operator<<(std::vector<T>& v1, T t1){
v1.push_back(T(t1));
return v1;
 } 

int main()  {
vector<string> s;
string s2(" hello ");
s << s2 ;
cout<< s[0];
return 0;}

so the T is string and v1 is of type vector(String) and t1 is of type String this is why i was wondering why removing typename T2 from template causes error even if the value_type is string for both

2 Answers2

1

i tried the following code i found on the net and is perfectly working.

template<typename T,typename T2>
std::vector<T>& operator<<(std::vector<T>& v1, T2 t1){
    v1.push_back(T(t1));
    return v1;
}

I wouldn't say that works perfectly:

  • The function argument t1 is accepted by value, which means a copy of the callers value is made. That's sometimes very inefficient. C++ has what's called move semantics that automates the efficient reuse of values when possible, you can get the benefit like this:

    template <typename T, typename T2>
    std::vector<T>& operator<<(std::vector<T>& v, T2&& t){
        v.emplace_back(std::forward<T2>(t));
        return v;
    }
    
  • << already has two common uses: bitwise shifting and output streaming; adding a third one exponentially increases the confusion. Someone with a vector<int> v might assume v << 3 would bitshift all the existing elements by 3, someone with vector<string> w might assume w << '.' would append a fullstop to each string currently stored, someone else might hope it creates a string of the existing elements joined by '.'s - all those hopes/expectations are as reasonable as what you're proposing, so anyone reading the client code would have to be open-minded enough to realise the operation is unclear and then dig in to find out what your << function's actually doing.

but for me the argument t1 must be from type T and not T2. so my first question is: why when i do

std::vector<T>& operator<<(std::vector<T>& v1, ***T t1***) //instead of T2 t1

Consider vector<double> v; v << 2; works even though 2 is an int not a double. It wouldn't work without your single template parameter.

i have the following error: error: no match for 'operator<<' (operand types are 'std::vector >' and 'std::string {aka std::basic_string}')

Your error message is garbled and you haven't (yet) posted your source code, so I can't say what you did wrong there....

YSC
  • 38,212
  • 9
  • 96
  • 149
Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
  • thanks for your answer! here is maybe a dumb question but in your argument " T2&& t" why do you use double & ? – user9446905 Mar 20 '18 at 15:01
  • 1
    @user9446905 you've a great deal to learn. It's dangerous to go alone, take this: [C++: What are move semantics?](https://stackoverflow.com/q/3106110/5470596) – YSC Mar 20 '18 at 19:02
  • @user9446905: in additiion to YSC's link, it's good to know speciificallly about `&&` - that's called a *forwarding reference* and used too be known as a *universal reference*. It means the caller can pass a movable value or a non-movable value, and when `std::forward` is used that "movability" will be properly passed on to the `emplace` function so the value will be moved into the vector if possible. – Tony Delroy Mar 22 '18 at 11:04
1

Even though you didn't explicitly ask for it, my crystal ball tells me you'd be interested in std::insert_iterator. Once an insert iterator is created on a container (vector, array, list, you name it!), you can add items to the container with an assignation syntax:

std::insert_iterator<std::vector<double>> ins(data, begin(data));
ins = 0;
ins = 1.f;
ins = 2.0;
ins = '\x03';
ins = 4ULL;

Or for a lighter syntax, you can help yourself with std::inserter():

auto ins = std::inserter(data, begin(data));
ins = /* ... */

This inserts 0.0 to 4.0 into the vector data. See an exemple of a complete program online.


Additional tools:

YSC
  • 38,212
  • 9
  • 96
  • 149