CWG Issue 1630 (original) (raw)
This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 117a. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2025-04-13
1630. Multiple default constructor templates
Section: 9.5 [dcl.init]Status: CD4Submitter: Nikolay IvchenkovDate: 2013-03-01
[Moved to DR at the November, 2014 meeting.]
It is unclear whether code like the following is supposed to be supported or not:
#include #include
#define ENABLE_IF(...)
typename std::enable_if<__VA_ARGS__, int>::type = 0
#define PRINT_VALUE(...)
std::cout << #VA_ARGS " = " << VA_ARGS << std::endl
struct undefined {};
template undefined special_default_value(T *);
template struct has_special_default_value : std::integral_constant < bool, !std::is_same < decltype(special_default_value((T *)0)), undefined >{} > {};
template struct X { template <class U = T, ENABLE_IF(!has_special_default_value{})> X() : value() {} template <class U = T, ENABLE_IF(has_special_default_value{})> X() : value(special_default_value((T *)0)) {} T value; };
enum E { e1 = 1, e2 = 2 };
E special_default_value(E *) { return e1; }
int main() { X x_int; X x_E; PRINT_VALUE(x_int.value); PRINT_VALUE(x_E.value);
PRINT_VALUE(X<int>().value);
PRINT_VALUE(X<E>().value);
}
The intent is that X should call the first default constructor and X should call the second.
If this is intended to work, the rules for making it do so are not clear; current wording reads as if a class can have only a single default constructor, and there appears to be no mechanism for using overload resolution to choose between variants.
Proposed resolution (June, 2014):
- Change 6.3 [basic.def.odr] paragraph 3 as follows:
...An assignment operator function in a class is odr-used by an implicitly-defined copy-assignment or move-assignment function for another class as specified in 11.4.5.3 [class.copy.ctor].
A default constructor for a class is odr-used by default initialization or value initialization as specified in 9.5 [dcl.init].A constructor for a class is odr-used as specified in 9.5 [dcl.init]. A destructor for a class is odr-used if it is potentially invoked (11.4.7 [class.dtor]).
- Change 9.5 [dcl.init] paragraph 7 as follows:
To default-initialize an object of type T means:
ifIf T is a (possibly cv-qualified) class type (Clause 11 [class]),the default constructor (11.4.5 [class.ctor]) for T is called (and the initialization is ill-formed if T has no default constructor or overload resolution (12.2 [over.match]) results in an ambiguity or in a function that is deleted or inaccessible from the context of the initialization);constructors are considered. The applicable constructors are enumerated (12.2.2.4 [over.match.ctor]), and the best one for the initializer () is chosen through overload resolution (12.2 [over.match]). The constructor thus selected is called, with an empty argument list, to initialize the object.ifIf T is an array type, each element is default-initialized;.otherwiseOtherwise, no initialization is performed.
- Change 11.4.5 [class.ctor] paragraph 4 as follows:
A default constructor for a class X is a constructor of class X that
can be called without an argumenteither has no parameters or else each parameter that is not a function parameter pack has a default argument. If there is no user-declared constructor...
- Change 12.2 [over.match] bullet 2.4 as follows:
Overload resolution selects the function to call in seven distinct contexts within the language:
- ...
- invocation of a constructor for default- ordirect-initialization (9.5 [dcl.init]) of a class object (12.2.2.4 [over.match.ctor]);
- ...
- Change 12.2.2.4 [over.match.ctor] paragraph 1 as follows:
When objects of class type are direct-initialized (9.5 [dcl.init]),
orcopy-initialized from an expression of the same or a derived class type (9.5 [dcl.init]), or default-initialized,overload resolution selects the constructor. For direct-initialization or default-initialization, the candidate functions are all the constructors of the class of the object being initialized. For copy-initialization, the candidate functions are all the converting constructors (11.4.8.2 [class.conv.ctor]) of that class. The argument list is the expression-list or assignment-expression of the initializer.