Corristo Corristo - 1 year ago 81
C++ Question

SFINAE with std::enable_if and std::is_default_constructible for incomplete type in libc++

I just observed a strange issue with libc++ when using SFINAE to detect if a templated type is default constructible.

The following is a minimal example I was able to come up with:

#include <iostream>
#include <type_traits>

template <typename T>
struct Dummy;

template <>
struct Dummy<int>{};

template <typename T, typename = void>
struct has_dummy : std::false_type {};

template <typename T>
struct has_dummy<C, std::enable_if_t<std::is_default_constructible<Dummy<T>>::value>> : std::true_type{};

int main() {
std::cout << std::boolalpha << has_dummy<int>{}() << '\n';
std::cout << std::boolalpha << has_dummy<double>{}() << '\n';
}


It compiles and outputs the expected lines
true
and
false
when compiled with g++ or clang++ when using
libstdc++
. However when I try to compile it with libc++ (i.e.
clang++ -stdlib=libc++ -std=c++1z test.cpp
) I get the following error:


/usr/bin/../include/c++/v1/type_traits:2857:38: error: implicit instantiation of undefined template
'Dummy'
: public integral_constant

/usr/bin/../include/c++/v1/type_traits:3166:14: note: in instantiation of template class
'std::__1::is_constructible>' requested here
: public is_constructible<_Tp>

test.cpp:14:43: note: in instantiation of template class 'std::__1::is_default_constructible >'
requested here

struct has_dummy<T, std::enable_if_t<std::is_default_constructible<Dummy<T>>::value>> : std::true_type{};


test.cpp:18:35: note: during template argument deduction for class template partial specialization
'has_dummy<type-parameter-0-0, typename enable_if<std::is_default_constructible<Dummy<T> >::value,
void>::type>' [with T = double]


std::cout << std::boolalpha << has_dummy<double>{}() << '\n';


test.cpp:5:8: note: template is declared here
struct Dummy;



Is this a bug in libc++'s implementation of
std::enable_if
or
std::is_default_constructible
or is what I'm doing somehow invoking undefined/implementation specific behaviour?

Best
Corristo

Answer Source

Preconditions for is_default_constructible state quite clearly:

N4140 ยง 20.10.4.3 [meta.unary.prop] / is_default_constructible row

T shall be a complete type, (possibly cv-qualified) void, or an array of unknown bound.

Which means that according to this answer, your program is ill-formed.