For certain reasons, I want to write a class A that behaves like this:
std::vector<int> x = A{1, 2, 3}; // [1,2,3]
std::vector<int> y = A{5}; // [5]
std::vector<int> z = A(5); // [0,0,0,0,0]
Most of this is simple (writing a conversion operator, etc), this is not what this question is about.
What I'm stuck at is, in A's constructor, detecting whether it was called using braces {...} or parentheses (...). I'm not sure if it's possible at all.
My best attempt is following: run on gcc.godbolt.org
#include <initializer_list>
#include <iostream>
template <bool Braces, typename ...P>
struct A
{
template <typename ...Q>
A(Q &&...)
{
std::cout << Braces << '\n';
}
};
struct Sink
{
template <typename T>
Sink(T &&);
};
template <typename ...P>
A(P &&...) -> A<false, P...>;
A(std::initializer_list<Sink>) -> A<true>;
int main()
{
A{1, 2, 3}; // 1 (except 0 in GCC)
A(1, 2, 3); // 0
}
But there are two issues here:
- It doesn't work in GCC (
Bracesis always false). - I no longer can deduce
P...from braces (the deduction guide above always deduces it to an empty list). I need it to store a tuple of the constructor arguments, to later use them in the conversion operator. I want the conversion operator to work for any type, so I can't construct the vector directly in the constructor.
Is this possible?