带有 std::enable_if 和 std::is_default_constructible 的 SFINAE 对于 libc++ 中的不完整类型
SFINAE with std::enable_if and std::is_default_constructible for incomplete type in libc++
我刚刚在使用 SFINAE 检测模板类型是否可默认构造时观察到 libc++ 的一个奇怪问题。
以下是我能够想出的一个最小示例:
#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';
}
当使用 libstdc++
使用 g++ 或 clang++ 编译时,它编译并输出预期的行 true
和 false
。但是,当我尝试使用 libc++(即 clang++ -stdlib=libc++ -std=c++1z test.cpp
)编译它时,出现以下错误:
/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;
这是 libc++ 的 std::enable_if
或 std::is_default_constructible
实现中的错误,还是我正在以某种方式调用 undefined/implementation 特定行为?
最佳
科里斯托
is_default_constructible
的前提条件非常明确:
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.
并且根据以下内容,您的程序表现出未定义的行为:
N4140 § 17.6.4.8 [res.on.functions] / 2
the effects are undefined in the following cases:
- [...]
- if an incomplete type (3.9) is used as a template argument when instantiating a template component, unless specifically allowed for
that component.
我刚刚在使用 SFINAE 检测模板类型是否可默认构造时观察到 libc++ 的一个奇怪问题。
以下是我能够想出的一个最小示例:
#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';
}
当使用 libstdc++
使用 g++ 或 clang++ 编译时,它编译并输出预期的行 true
和 false
。但是,当我尝试使用 libc++(即 clang++ -stdlib=libc++ -std=c++1z test.cpp
)编译它时,出现以下错误:
/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;
这是 libc++ 的 std::enable_if
或 std::is_default_constructible
实现中的错误,还是我正在以某种方式调用 undefined/implementation 特定行为?
最佳 科里斯托
is_default_constructible
的前提条件非常明确:
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.
并且根据以下内容,您的程序表现出未定义的行为:
N4140 § 17.6.4.8 [res.on.functions] / 2
the effects are undefined in the following cases:
- [...]
- if an incomplete type (3.9) is used as a template argument when instantiating a template component, unless specifically allowed for that component.