C++ 构造函数重载与SFINAE

C++ 构造函数重载与SFINAE,c++,c++14,enable-if,C++,C++14,Enable If,作为理解std::enable_用法的练习,如果I尝试实现包装类(struct)来表示任意给定时间点的特定类型: #include<type_traits> #include<typeinfo> #include<iostream> using std::enable_if; using std::is_same; using std::cout; using std::endl; template<typename T> struct type

作为理解
std::enable_用法的练习,如果
I尝试实现包装类(struct)来表示任意给定时间点的特定类型:

#include<type_traits>
#include<typeinfo>
#include<iostream>
using std::enable_if;
using std::is_same;
using std::cout;
using std::endl;

template<typename T>
struct type_wrap{

                 type_wrap(typename enable_if<is_same<int,T>::value,T>::type&& rrT):value(rrT){
                         cout << "The wrapped type is " << typeid(value).name() << endl;
                         cout << "The wrapped value is " << value << endl;
                } 
                 type_wrap(typename enable_if<is_same<float,T>::value,T>::type && rrT):value(rrT){
                         cout << "The wrapped type is " << typeid(value).name() << endl;
                         cout << "The wrapped value is " << value << endl;
                 }

                 T& value;
};

int main(){

        type_wrap<int>(0);
        type_wrap<float>(0.5);
        return(0);
}
#包括
#包括
#包括
使用std::enable_if;
使用std::是相同的;
使用std::cout;
使用std::endl;
模板
结构类型{
type_wrap(typename enable_if::type&&rrT):值(rrT){
库特
有人能指出编译错误的原因吗

因为
std::enable_if
将使您的一个构造函数非法,具体取决于:

type_wrap<int>(0);
type_wrap<float>(0.5);
相反,请按如下方式使用模板专门化:

template<typename T>
struct type_wrap;

template<>
struct type_wrap<float>
{
    type_wrap(float&& rrT) :value(rrT) {
        cout << "The wrapped type is " << typeid(value).name() << endl;
        cout << "The wrapped value is " << value << endl;
    }

    float& value;
};

template<>
struct type_wrap<int>
{
    type_wrap(int&& rrT) :value(rrT) {
        cout << "The wrapped type is " << typeid(value).name() << endl;
        cout << "The wrapped value is " << value << endl;
    }

    int& value;
};

SFINAE使用模板方法(/constructor),这里是您的类,它是模板,您可以使用以下方法(即使在您的情况下专门化看起来更简单/更好):

模板
结构类型{
模板
类型_wrap(U arg):值(arg){
//整箱

感谢您的解释,但我不太明白。我的理解是使用enable_if()的目的是根据特定的实例化只启用一个重载。您的观察结果“int或double将反作用于std::is_的另一面,即有false,”我不清楚。即使在main()中只使用一个实例化,即int或float,我也会遇到类似的错误@user9196120如果
T
float
,则第一个构造函数是非法的。如果
T
int
,则第二个构造函数是非法的。在这种情况下没有SFINAE-编译器必须看到两个构造函数在这两种情况下都有效。@user9196120:Typo-fixed,Demo-added
在传递
double
而不是
float
时对我的版本无效。而专门化会创建允许转换/升级的非模板方法。@@Jarod421能否提供一个解释。关于为什么要使用*来启用\u if\t并将其设置为null ptr?我对所涉及的逻辑很好奇,不确定是否理解你可以看看哪个显示了使用
std::enable\u if
的不同方式。
template<bool B, class T = void>
struct enable_if {}; // int or float will get this on each constructor.

template<class T>
struct enable_if<true, T> { typedef T type; };
template<typename T>
struct type_wrap;

template<>
struct type_wrap<float>
{
    type_wrap(float&& rrT) :value(rrT) {
        cout << "The wrapped type is " << typeid(value).name() << endl;
        cout << "The wrapped value is " << value << endl;
    }

    float& value;
};

template<>
struct type_wrap<int>
{
    type_wrap(int&& rrT) :value(rrT) {
        cout << "The wrapped type is " << typeid(value).name() << endl;
        cout << "The wrapped value is " << value << endl;
    }

    int& value;
};
template<typename T>
struct type_wrap
{
    type_wrap(T&& rrT):value(rrT)
    {
        if constexpr (std::is_same<int, T>::value)
        {
            cout << "The wrapped type is " << typeid(value).name() << endl;
            cout << "The wrapped value is " << value << endl;
        }
        else
        {
            cout << "The wrapped type is " << typeid(value).name() << endl;
            cout << "The wrapped value is " << value << endl;
        }
    } 

    T& value;
};
template<typename T>
struct type_wrap{
    template <typename U,
              std::enable_if_t<std::is_same<int, U>::value
                               && is_same<int, T>::value>* = nullptr>
    type_wrap(U arg) : value(arg){
        // Int case
        std::cout << "The wrapped type is " << typeid(value).name() << std::endl;
        std::cout << "The wrapped value is " << value << std::endl;
    }

    template <typename U,
              std::enable_if_t<std::is_same<float, U>::value
                               && is_same<float, T>::value>* = nullptr>
    type_wrap(U arg) : value(arg){
        // float case
        std::cout << "The wrapped type is " << typeid(value).name() << std::endl;
        std::cout << "The wrapped value is " << value << std::endl;
    }
    T value;
};