enable_if 两个版本的用法不同

Two versions of enable_if usage work differently

我无法理解为什么两个版本的复制构造函数的工作方式不同(因为 enable_if)。

template <typename Type>
struct Predicate : std::integral_constant<bool, true>
{
};
template <>
struct Predicate<int> : std::integral_constant<bool, false>
{
};

template <typename FooType>
struct Settings
{
    Settings() {}

    //  Here it works fine
    template <typename OtherFooType>
    Settings(const Settings<OtherFooType>& other, std::enable_if_t<Predicate<OtherFooType>::value, int*> = 0) {}

    //  In this case enable_if does not work
    //template <typename OtherFooType>
    //Settings(typename std::enable_if<Predicate<OtherFooType>::value, const Settings<OtherFooType>&>::type other){}
};

int main()
{
    Settings<float> f = Settings<char>();
    return 0;
}

在我看来,enable_if 是 SFINAE 有条件地删除复制构造函数的方法。它应该适用于这两种情况。也许我缺少对 SFINAE 的理解?

在第二个示例中,模板参数 OtherFooType 仅出现在函数参数中范围解析运算符 :: 的左侧。

在限定名称指定的类型中 :: 剩下的所有内容都是 non-deduced 上下文,这意味着 OtherFooType 的模板参数不会从函数 parameter/argument pair.

推导出来

因此无法推导出 OtherFooType,因此构造函数始终为 non-viable.

SFINAE 甚至无关紧要,因为只有在 成功推导后发生替换时,SFINAE 才有意义。

此外,构造函数模板(的特化)永远不是复制构造函数。这些是转换构造函数,复制构造函数仍将隐式声明。