【问题标题】:SFINAE with std::enable_if and std::is_default_constructible for incomplete type in libc++带有 std::enable_if 和 std::is_default_constructible 的 SFINAE 用于 libc++ 中的不完整类型
【发布时间】:2017-04-10 20:32:33
【问题描述】:

在使用 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';
}

当使用 g++ 或 clang++ 编译时,它会编译并输出预期的行 truefalse,而使用 libstdc++。但是,当我尝试使用 libc++(即clang++ -stdlib=libc++ -std=c++1z test.cpp)编译它时,我收到以下错误:

/usr/bin/../include/c++/v1/type_traits:2857:38:错误:未定义模板的隐式实例化 '假的' : 公共积分常数

/usr/bin/../include/c++/v1/type_traits:3166:14: 注意:在模板类的实例化中 'std::__1::is_constructible>' 在这里请求 : public is_constructible<_tp>

test.cpp:14:43: 注意:在模板类 'std::__1::is_default_constructible >' 的实例化中 在这里请求 struct has_dummy<T, std::enable_if_t<std::is_default_constructible<Dummy<T>>::value>> : std::true_type{};

test.cpp:18:35:注意:在类模板部分特化的模板参数推导期间 '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: 注意:模板在这里声明 struct Dummy;

这是 libc++ 的 std::enable_ifstd::is_default_constructible 实现中的错误,还是我正在做的事情以某种方式调用未定义/实现特定的行为?

最好的 科里斯托

【问题讨论】:

    标签: c++ templates language-lawyer sfinae libc++


    【解决方案1】:

    is_default_constructible 的前提条件非常明确:

    N4140 § 20.10.4.3 [meta.unary.prop] / is_default_constructible

    T 应该是一个完整的类型,(可能是 cv-qualified)void,或者一个 未知边界数组。

    根据以下情况,您的程序表现出未定义的行为:

    N4140 § 17.6.4.8 [res.on.functions] / 2

    在以下情况下效果未定义:

    • [...]
    • 如果在实例化模板组件时将不完整类型 (3.9) 用作模板参数,除非特别允许 该组件。

    【讨论】:

    • 在库中,除非另有说明,否则破坏前提条件会导致未定义的行为。
    • @T.C.好吧,看来我几乎每天都从你那里学到新东西 :) 现在还好吗?我不确定 res.on.functions 或 res.on.required 是否适用。后者有更好的名称,但明确提到了函数,并且特征不是函数,除非它们以不同的方式使用函数这个词
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-08
    • 1970-01-01
    • 2020-10-16
    • 1970-01-01
    • 1970-01-01
    • 2014-07-21
    相关资源
    最近更新 更多