struct A
{
A(int) {}
A(std::initializer_list<int>) {}
};
template<typename T>
struct B
{
B(A) {}
B(std::initializer_list<T>) {}
};
int main()
{
int n{};
B m1(A{n}); // error: call A::A(std::initializer_list<int>)
B m2(A(n)); // error: just a function declaration: B m2(A n);
}
As shown in the code above, I want to call B::B(A(int))
to construct an object of class B
. I have two choices:
B m1(A{n});
B m2(A(n));
According to C++ Core Guidelines, the former is preferred.
However, B m1(A{n});
will call A::A(std::initializer_list<int>)
rather than A::A(int)
, which is not intended. So, I have to use B m2(A(n));
, but it is just a function declaration: B m2(A n);
!
How to solve ambiguous declarations elegantly in C++11?
The almost always auto idiom to the rescue.
I'm not sure what you intended T to be, since it is unclear in the code example. I used double
because... why not.
int main() {
auto n = int{};
auto m1 = B<double>(A{n});
auto m2 = B<double>(A(n));
}
Disclaimer: about half the C++ developers I talk to in real life (at my job) absolutely despise almost always auto. I like it (but I've done a lot of C# with var
, F#, and TypeScript, where that's business as usual; and C++ template code and lambda-with-auto), but there are many who are ardently anti auto. If you decide to use almost always auto in your own project, I strongly urge you to discuss with your co-workers and get team consensus before going down that path.