How Could Comma Separated Initialization Such as in Eigen Be Possibly Implemented in C++

How could comma separated initialization such as in Eigen be possibly implemented in C++?

The basic idea is to overload both the << and the , operators.

m << 1 is overloaded to put 1 into m and then returns a special proxy object – call it p – holding a reference to m.

Then p, 2 is overloaded to put 2 into m and return p, so that p, 2, 3 will first put 2 into m and then 3.

A similar technique is used with Boost.Assign, though they use += rather than <<.

initializing a static eigen matrix with comma initialization

Oh, I got this.

This code:

s_idRotationZinverse.col(0) << s_yAxis;

isn't a declaration; it's a statement that has to be inside a function body.

You're probably trying to execute it outside of any function, which is syntactically incorrect and causes the error you mentioned.

You might have been tricked by the Eigen documentation, which calls this syntax "comma initialization" where it should be "comma assignment" or so. Initialization is when you give the variable a value when it's defined, not as a separate step. Initialization is syntactically a part of the declaration, so it can be done outside of function bodies.

I suggest to fork Eigen to support the new std::initializer_list-based initialization (if it's not done yet) and submit a pull request.

When to Overload the Comma Operator?

Let's change the emphasis a bit to:

When should you overload the comma?

The answer: Never.

The exception: If you're doing template metaprogramming, operator, has a special place at the very bottom of the operator precedence list, which can come in handy for constructing SFINAE-guards, etc.

The only two practical uses I've seen of overloading operator, are both in Boost:

  • Boost.Assign
  • Boost.Phoenix – it's fundamental here in that it allows Phoenix lambdas to support multiple statements

operator with multiple parameters

No, that is not possible.

The closest you can come would be something like:

anyType         operator<<(std::pair<arg, arg> p)
{
DoSomethingWith(p.first);
DoSomethingWith(p.second);
return (*this);
}

anyvar << std::make_pair(a1, a2);

Alternatively, you could do something much more complicated to effectively curry the call to your operator, by having anyType::operator<<(arg) return a temporary object which just holds on to its argument and implements a different tempObject::operator<<(arg) which actually does the work. You can then call that as anyvar << arg1 << arg2. I really doubt whether it is worth the trouble, aside from being a learning experience.

Something similar to that style is often used in the "builder" pattern, but using member functions rather than an explicit operator. That's useful because you can arrange to effectively make configuration arguments order-independent.

Template for variable length initializer

Don't use the comma initializer syntax in this setting, it's going to be cumbersome. This syntax is used for readability when using literals, which is not your case.

Instead, I would recommend something like:

template<typename T1, typename T2, unsigned int SIZE, unsigned int INDEX>
struct gather {
gather(Array<T1,SIZE,1> &to,
const Array<T2,Dynamic,1> &from,
const Array<int,SIZE,1> &index)
{
to.col(INDEX) = from[index[INDEX]];
gather<T1,T2,SIZE,INDEX+1>(to,from, index);
}
};

template<typename T1, typename T2, unsigned int SIZE>
struct gather<T1,T2,SIZE,SIZE>{
gather(Array<T1,SIZE,1> &to,
const Array<T2,Dynamic,1> &from,
const Array<int,SIZE,1> &index)
{
}
};

which nicely produces the same effect, but statically (no loop).

I am using a struct here because of the partial template specialization restriction on functions, but it should come down to the same, because of inlining.

What is the easiest way to initialize a std::vector with hardcoded elements?

One method would be to use the array to initialize the vector

static const int arr[] = {16,2,77,29};
vector<int> vec (arr, arr + sizeof(arr) / sizeof(arr[0]) );


Related Topics



Leave a reply



Submit