Problems with enable_if SFINAE

Problems with enable_if SFINAE

本文关键字:if SFINAE enable with Problems      更新时间:2023-10-16

我在编写的程序中遇到了一些莫名其妙的SFINAE问题,所以我把它归结为一个独立的示例程序:

#include <type_traits>
struct Base { };
struct Derived : public Base { };
template<typename T>
struct From { };
template<typename T>
struct To {
    template<typename U>
    To(const From<U>& other) {
        static_assert(std::is_convertible<U*, T*>::value, "error");
    }
};
int main() {
    From<Derived> a;
    To<Base> b = a;
}

此程序编译时没有出现错误或警告。然而,这:

#include <type_traits>
struct Base { };
struct Derived : public Base { };
template<typename T>
struct From { };
template<typename T>
struct To {
    template<typename U>
    To(const From<typename std::enable_if<true, U>::type>& other) {
    // this       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        static_assert(std::is_convertible<U*, T*>::value, "error");
    }
};
int main() {
    From<Derived> a;
    To<Base> b = a;
}

给出以下错误:

test.cpp:在函数int main():中

test.cpp:22:18:错误:从From<Base>转换为非标量类型To<Derived>请求

这是因为我认为替换失败了,并且看不到构造函数。

我做错了SFINAE,还是这是一个编译器错误?我在Windows上使用的是ruenvb的GCC 4.7.1(如果std=c++11有区别的话)。

我会使用默认的模板参数,这样就可以推导出参数:

#include <type_traits>
struct Base { };
struct Derived : public Base { };
template<typename T>
struct From { };
template<typename T>
struct To {
    template<typename U, class = typename std::enable_if<true, U>::type>
    To(const From<U>& other) {
    // this       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        static_assert(std::is_convertible<U*, T*>::value, "error");
    }
};
int main() {
    From<Base> a;
    To<Derived> b = a;
}

请注意,这会导致static_assert失败,因为您使用的是相反的std::is_convertible。应该是:

static_assert(std::is_convertible<T*, U*>::value, "error");

在您的示例中,无法推导出模板类型U。在我的代码中,它可以被推导出来,因为它被用作构造函数中other参数的模板参数。在您的代码中,编译器看到一个std::enable_if<true, U>::type,但无法推断出该U类型是什么。该enable_if的结果被用作From的模板参数这一事实根本没有帮助,因为在此之前需要推断出U