Consider the following code:
#include <vector>
struct A
{
explicit A(int i_) : i(i_) {}
int i;
};
int main()
{
std::vector<int> ints;
std::vector<A> As(ints.begin(), ints.end());
}
Should the above compile? My feeling is that it should not, due to the constructor being marked explicit.
Microsoft Visual C++ agrees, giving a clear error message: cannot convert from 'int' to 'const A'; Constructor for struct 'A' is declared 'explicit'
However, using Comeau’s online compiler, the code compiles successfully.
Which is correct?
Edit:
Interestingly, changing vector to set (after adding an operator < to A) causes both compilers to give an error.
However, changing vector<int> to map<int, int> and vector<A> to map<A, A> causes both compilers to accept the code!
I looked through GCC’s STL implementation and it should have similar behavior. Here’s why.
vectorare initialized by a generic function template which accepts any two typesXandVand callsnew( p ) X( v )wherevis aV(I’m paraphrasing a bit). This allows explicit conversion.setormapare initialized by a private member function of_tree<T,…>which specifically expects aT const &to be passed in. This member function isn’t a template (beyond being a member of a template), so if the initial value can’t be implicitly converted toT, the call fails. (Again I’m simplifying the code.)The standard doesn’t require that explicit conversion work or that implicit conversion not work when initializing a container with a range. It simply says that the range is copied into the container. Definitely ambiguous for your purpose.
Surprising such ambiguity exists, considering how they’ve already refined the standard in consideration of problems like the one I had a couple weeks ago.