成员函数 SFINAE 错误 C2938

member function SFINAE error C2938

此代码在 VS2013 中编译失败。

template<typename T>
class SomeClass {
public:
    std::enable_if_t<std::is_fundamental<T>::value, T>
        DoSomething() {
        return T();
    }

    std::enable_if_t<!std::is_fundamental<T>::value, T>
        DoSomething() {
        return T();
    }
};

如何在VS2013中实现(DoSomething必须是非静态成员函数)?

SFINAE 仅适用于模板。您的 DoSomething() 不是模板,它是 class 模板的非模板成员。您需要将其设为模板:

template<typename T>
class SomeClass {
public:
    template <class U = T>
    std::enable_if_t<std::is_fundamental<U>::value, T>
        DoSomething() {
        return T();
    }

    template <class U = T>
    std::enable_if_t<!std::is_fundamental<U>::value, T>
        DoSomething() {
        return T();
    }
};

[Live example]

来自here

Only the failures in the types and expressions in the immediate context of the function type or its template parameter types are SFINAE errors.

要在 DoSomething 的分辨率下获得 SFINAE,您需要通过另一个模板参数引入直接上下文并检查它是否为 T

template<typename T>
class SomeClass {
public:
    template <typename U = T> 
    std::enable_if_t<std::is_fundamental<U>::value && std::is_same<U,T>::value, T>
        DoSomething() {
        return T();
    }

    template <typename U = T> 
    std::enable_if_t<!std::is_fundamental<U>::value && std::is_same<U,T>::value, T>
        DoSomething() {
        return T();
    }
};

添加了 std::is_same 检查以防止有人调用 SomeClass::DoSomething<U>U 不是 T.

的类型

标签调度感觉比 SFINAE 更干净:

template<typename T>
class SomeClass {
private:
    T DoSomethingImpl(std::true_type /*is_fundamental*/) { return T(); }
    T DoSomethingImpl(std::false_type /*is_fundamental*/) { return T(); }
public:
    T DoSomething() {
        return DoSomethingImpl(std::is_fundamental<T>());
    }
};