1

I'm trying to accomplish something similar to Eigen advanced initialization for my container class.

i.e. in main, I want to fill an object of type DynamicArray as follows:

main.cpp

// Create 3 x 3 Dynamic array and fill with 0's DynamicArray da(3, 3, 0); da << 1, 2, 3, 4, 5, 6, 7, 8, 9; 

The method I've used to try to accomplish this is:

DynamicArray.hpp

template <typename T> class DynamicArray { // ... public: // ... template <typename... Args, typename = typename std::enable_if<ArgPackSameTruth< std::is_convertible<Args, T>...>::value, T>::type > void operator<<(Args... x) { typename std::vector<T> arg_vect{std::forward<Args>(x)...}; std::cout << arg_vect.size() << "\n"; // Load contents of arg_vect into *this... return; } } 

When I compile main.cpp, I get a size of 1 for arg_vect, so only the first parameter is being taken in. How can I make sure all parameters are passed?

Thanks!

2
  • You may make your operator overload return *this so that it can become possible to chain da << 1 << 2 //... calls. Commented Jul 19, 2014 at 16:35
  • operator overloading doesn't magically change the number of operands. Commented Jul 19, 2014 at 17:06

2 Answers 2

5

The order of operations is different from what you seem to think. If you have:

da << 1, 2, 3; 

it is equivalent to (given free operators):

auto tmp1 = operator<<(da,1); auto tmp2 = operator,(tmp1,2); auto tmp3 = operator,(tmp2,3); 

hence you'd need operators roughly like this:

#include <iostream> struct DynamicArray { }; DynamicArray& operator<<( DynamicArray& da, int i ) { std::cout << "<<" << i << std::endl; return da; } DynamicArray& operator,( DynamicArray& da, int i ) { std::cout << "," << i << std::endl; return da; } int main() { DynamicArray da; da << 1, 2, 3, 4, 5, 6, 7, 8, 9; } 

Live example

Of course you need to store the values somewhere, etc. Think about a design which allows this and consider adding an intermediate class to hold the values which is returned by operator<< and which works as both the first input parameter and the return type for operator,. The destructor of that class can be used to apply the collected intermediate data if needed.

Sign up to request clarification or add additional context in comments.

1 Comment

Note that da, 1,2,3,4,5 also puts numbers into da, which is not desired/
2

operator << only takes 1 argument. That's why the size is 1. The numbers after 1 are all unused. If you turn on -Wall you should get a warning about this.

I can think of 2 solutions.

One would be to simply enclose the numbers in braces {...} and let operator << accept a std::initializer_list<double>

void operator<< (std::initializer_list<double>);

Second solution would be to have Dynamic array overload operator,and operator<<

Both , and << would return a DynamicArray so that they could be chained.

DynamicArray& operator<<(double x){ //Add x to the Dynarray return *this; } 

operator, Would do the same thing as operator<<

DynamicArray& operator, (double x){ //Add x to the Dynarray return *this; } 

Here is a baisic example for std::vector

#include <vector> #include <iostream> template <typename T> std::vector<T>& operator<<(std::vector<T>& x, T y) { x.push_back(y); return x; } template <typename T> std::vector<T>& operator,(std::vector<T>& x, T y) { x.push_back(y); return x; } int main(){ std::vector<int> A; A << 1,2,3,4,5,6,7,8,9,10; for(int x : A){ std::cout << x << ","; } std::cout << std::endl; } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.