2016-07-28 91 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

相關問題