SFINAE 条件和构造函数参数类型

SFINAE conditional and constructor argument types

我遇到了以下允许围绕 T 构造包装器对象的技术,但是从 U 类型的对象,如果 T 可以从 [=12= 构造]:

template< typename T >
struct S {
    template< typename U,
              typename = std::enable_if_t<
                  std::is_constructible< T, U >::value > >
    explicit S (U&& arg) : value (arg)
        { }
    ...
};

IIUC,is_constructible测试中使用的类型U可以不同于arg.
的cv限定类型 尽管表达式 value(arg) 有效,但 SFINAE 测试是否有可能失败?

Is it possible that the SFINAE test could fail although the expression value(arg) is valid?

你写的方式S:是的,这是可能的。
它遵循一个最小的(不是)工作示例:

#include<type_traits>

template< typename T >
struct S {
    template< typename U
              , typename = std::enable_if_t<std::is_constructible< T, U >::value >
    > explicit S (U&& arg) : value{arg} {}

    T value;
};

struct A {};
struct B {
    B(A &) {}
};

int main() {
    S<B> s(A{});
}

上面的代码无法编译,但如果您注释掉以下行,它会编译:

, typename = std::enable_if_t<std::is_constructible< T, U >::value >

问题是你没有转发构造函数参数。相反,您使用对 A(即 arg)类型右值引用的变量的左值引用作为 value.
的参数 B 不能从对 A 的右值引用构造,并且 sfinae 表达式失败(正确),但您实际上并没有使用这样的引用来构造参数,因此删除它有效的 sfinae 表达式。
事实上,B 可以从对 A 的左值引用构造,这就是您在编写 value{arg}.

时使用的内容

您应该这样写 S

#include<utility>

// ...

template< typename T >
struct S {
    template< typename U
              , typename = std::enable_if_t<std::is_constructible< T, U >::value >
    > explicit S (U&& arg) : value (std::forward<U>(arg)) { }

    T value;
};

注意使用 std::forward 实际转发具有正确类型的参数。
这至少解决了上面提到的问题,它应该给你你正在寻找的保证。