2016-07-28 82 views
6

是否可以使用SFINAE和std::enable_if来禁用模板类的单个成员函数?使用SFINAE禁用模板类成员函数


目前,我有一个类似的代码:

#include <type_traits> 
#include <iostream> 
#include <cassert> 
#include <string> 

class Base { 
public: 
    virtual int f() { return 0; } 
}; 

template<typename T> 
class Derived : public Base { 
private: 
    T getValue_() { return T(); } 

public: 
    int f() override { 
     assert((std::is_same<T, int>::value)); 
     T val = getValue_(); 
     //return val; --> not possible if T not convertible to int 
     return *reinterpret_cast<int*>(&val); 
    } 
}; 


template<typename T> 
class MoreDerived : public Derived<T> { 
public: 
    int f() override { return 2; } 
}; 


int main() { 
    Derived<int> i; 
    MoreDerived<std::string> f; 
    std::cout << f.f() << " " << i.f() << std::endl; 
} 

理想的情况下,应Derived<T>::f()如果T != int被禁用。由于f是虚拟的,因此即使从未调用过Derived的实例,也会生成Derived<T>::f()。 但是,代码的使用方式使得Derived<T>(与T != int)不会仅作为MoreDerived<T>的基类创建。

所以在编译Derived<T>::f()时需要进行编译; reinterpret_cast行永远不会被执行。

+2

什么模板专业化的诠释? – wasthishelpful

回答

6

你可以简单地为专门intf

template<typename T> 
class Derived : public Base { 
private: 
    T getValue_() { return T(); } 

public: 
    int f() override { 
     return Base::f(); 
    } 
}; 

template <> 
int Derived<int>::f() { 
    return getValue_(); 
} 
5

不,您不能排除SFINAE的成员函数。您可以将Derived类别f成员函数专用于可转换T s到int,但这会导致不必要的代码重复。在C++ 17然而,你可以在使用的if constexpr解决这个问题:

template<typename T> class Derived : public Base { 
    T getValue_() { return T(); } 
public: 
    int f() override { 
    if constexpr(std::is_convertible<T, int>::value) return getValue_(); 
    return Base::f(); 
    } 
}; 

Live Demo