2014-04-15 71 views
6

在「太陽下沒有新東西」的規則下運作,我懷疑我是第一個想出這個竅門的人。我想我會偶然在網上記錄它,但我還沒有,所以我想我會問。這個SFINAE模式有一個名字嗎?

其目的是有選擇地啓用某些功能,只要它們相關,而不使用派生類。

這種模式是否有名稱?還有人有任何有關這種模式或類似的模式有用的信息?

template<typename T, size_t N> 
class Point { 
public: 
    template<size_t P, typename T2=void> 
    using Enable2D = typename std::enable_if<P == 2 && N == P, T2>::type; 
    template<size_t P, typename T2=void> 
    using Enable3D = typename std::enable_if<P == 3 && N == P, T2>::type; 
    template<size_t P, typename T2=void> 
    using Enable4D = typename std::enable_if<P == 4 && N == P, T2>::type; 
    template<size_t P, typename T2=void> 
    using Enable2DOrHigher = typename std::enable_if<P >= 2 && N == P, T2>::type; 
    template<size_t P, typename T2=void> 
    using Enable3DOrHigher = typename std::enable_if<P >= 3 && N == P, T2>::type; 
    template<size_t P, typename T2=void> 
    using Enable4DOrHigher = typename std::enable_if<P >= 4 && N == P, T2>::type; 

    //Example use cases 
    template<size_t P=N> 
    static Enable2D<P, Point> withAngle(T angle, T magnitude = 1); 
    template<size_t P=N> 
    static Enable3D<P, Point> fromAngles(T psi, T theta, T magnitude = 1); 

    template<size_t P=N> 
    Enable2DOrHigher<P, T> const& x() const; 
    template<size_t P=N> 
    Enable2DOrHigher<P, T> const& y() const; 
    template<size_t P=N> 
    Enable2DOrHigher<P> setX(T const& t); 
    template<size_t P=N> 
    Enable2DOrHigher<P> setY(T const& t); 

    template<size_t P=N> 
    Enable3DOrHigher<P, T> const& z() const; 
    template<size_t P=N> 
    Enable3DOrHigher<P> setZ(T const& t); 

    template<size_t P=N> 
    Enable4DOrHigher<P, T> const& w() const; 
    template<size_t P=N> 
    Enable4DOrHigher<P> setW(T const& t); 
}; 
+0

這是一個有趣的想法 - 本質上參數化成員函數指針。在JavaScript中,您可以構建「原型」對象,從而有條件地創建某些成員函數。我在C++中沒有見過類似的東西。好奇地看到回覆...... –

+0

對此的激勵用例是我們也有多維線和盒類,它們都採用了標準點,但是我們之前有過派生類的point2和point3,所以有用的2d和3d點函數對類本身來說都是不可訪問的(除非我們也要派生它們,在這種情況下,它將是一個重新實現,因爲成員已經改變了,並且有很多通用代碼,DRY),而且還包含任何代碼片段使用框和線算法。所以我們覺得使用SFINAE更清潔,即使它使得暴露的函數稍微不一致。 – OmnipotentEntity

+0

爲什麼要重複使用'enable_if'成爲一種模式?這是'enable_if'的典型應用 - 例如考慮[cppreference的描述](http://en.cppreference.com/w/cpp/types/enable_if)「*有條件地從基於類型特徵的重載解析中移除函數和類,併爲不同類型特徵提供單獨的函數重載和特化*「......似乎包含了你所做的完全充分的事情。 –

回答

4

我不會稱之爲模式,但它是一種已知技術。

大部分被認爲是條件接口該技術主要解決編譯時切換機制打開和關閉類的接口的問題。整個過程提供了切換成員存在的工具(所以術語條件編譯誕生了)。

該技術或多或少地按照您的建議實施(雖然缺少別名模板在C++ 11之前不是問題),而通常的問題是重型,混亂,混亂和「醜陋」的模板機制樣板代碼。

解決此問題,A. Alexandrescugave a presentation關於該主題。最初,有需求的這種技術小提的是:

enter image description here

,說

  • 此功能僅適用於數字

被reffering到你的技術和子彈需要有編譯時條件來切換函數的存在(條件接口)。

談話繼續提出一個新的語言功能。由於我們都發明瞭幾次輪子,所以爲什麼不用一種新的語言語法,這將允許我們執行這樣的事情。他的joint workH. Sutter,生產static if一個編譯時間切換器,將消除您提到的變通方法的需求。一個簡單的使用這將是

template<int D> 
struct Vector 
{ 
    double coordinates[D]; 
    static if (D) { 
     double x() { return coordinates[0]; } 
    } 
    static if (D > 1) { 
     double y() { return coordinates[1]; } 
    } 
    static if (D > 2) { 
     double z() { return coordinates[2]; } 
    } 
}; 

好吧也許這不是最聰明的使用它,但我想我是溝通的想法。

在相對的現在,B. Stroustroup發表了paper其中aknowledging static if是解決問題之後,他解釋了爲什麼這是一個有缺陷的概念(雙關語意:))及其通過將是對災難語言(哎!)。

這是我的兩分錢,從這次「對話」的參與者的級別來看,我想就他們在哪一方有一些反饋意見,或者他們是否是標準化流程的一部分。他們會投票嗎?

+1

我不瞭解很多歷史,但也許是那時Alexandrescu決定繼續[D路](http://dlang.org/cpptod.html#metatemplates)... – iavr

相關問題