Consider the following code:
template <typename... Types>
struct list
{
template <typename... Args>
list(Args...)
{
static_assert(sizeof...(Types) > 0);
}
};
template <typename... Args>
list(Args...) -> list<Args...>;
int main()
{
list l{0, 0.1, 'a'};
}
I would expect decltype(l)
to be list<int, double, char>
. Unfortunately, g++ 7.2 and g++ trunk fail the static assertion. clang++ 5.0.0 and clang++ trunk compile and work as expected.
Is this a g++ bug? Or Is there a reason why the deduction guide should not be followed here?
Adding a SFINAE constraint on the constructor seems to provide the desired behavior:
template <typename... Args,
typename = std::enable_if_t<sizeof...(Args) == sizeof...(Types)>>
list(Args...)
{
static_assert(sizeof...(Types) > 0);
}
This is gcc bug 80871. The issue is, we end up with this set of candidates for deduction:
Both are valid (
Types...
can deduce as empty in the first case), but the call here should be ambiguous - neither is more specialized than the other.Types...
does not participate in ordering here (similar to the example in [temp.deduct.partial]/12). So the correct behavior is to proceed to the next tiebreaker, which favors deduction-guides. Hence, this should be alist<int, double, char>
.However, gcc's behavior is to favor the constructor, hence the
static_assert
triggers becuaseTypes...
would indeed be empty in that situation.