2012-08-24 71 views
0

我有一個模板化的類,我想只在類型爲double時啓用某個構造函數。這段代碼有什麼問題?Boost enable_if在構造函數中

template<typename T> 
class B: public A<T> 
{ 
public: 
    B(int arg1=0, typename boost::enable_if_c<boost::is_same<T, double>::value>=0); 
} 

int main(int argc,char *argv[]) 
{ 
B<double> B(6, 6); 
} 

,我發現了錯誤:「默認參數類型的參數‘的boost :: enable_if_c’有型‘詮釋’」,但我不知道是什麼這意味着。

非常感謝你提前。

+1

貌似失蹤':: type' – Mat

+0

,而遺漏的「詮釋」 – ysdx

+1

什麼你想實現嗎?你編碼的是'B只能在T是雙的時候實例化'。但是,那麼使用'template'是什麼?在這種情況下,SFIANE不起作用,因爲'T'是類參數,而不是函數1。 – Lol4t0

回答

0
B(int arg1=0, typename boost::enable_if_c<boost::is_same<T, double>::value>=0); 

你忘了第二個參數boost::enable_if_c指定的類型,你忘了::type,你忘了一個參數名稱。

如果你想沿着B(int arg1=0, int arg2=0)線的東西,用

B(int arg1=0, 
    typename boost::enable_if_c<boost::is_same<T, double>::value, int>::type arg2=0); 

更妙的是,請不要使用,如果啓用的下劃線C版。只需使用啓用如果:

B(int arg1=0, 
    typename boost::enable_if<boost::is_same<T, double>, int>::type arg2=0); 
+2

Ehm。 ':: type'在哪裏? – ForEveR

+0

Ehm - 對。謝謝。 –

+0

這不起作用。 – mfontanini

2

您不能在這種情況下使用SFIANE,因爲它只能如果功能模板參數枷替換,而不是當模板參數的替換將失敗。

你需要什麼是專業化

但據我所知,您應該在您的double的情況下複製常見情況的執行,但只能添加新的構造函數。

在這種情況下,我建議我使用一些有線技術:您可以從您的專業化中的常見情況中派生出來。

那麼你面臨兩個問題:

  1. 你還應該有專門的double常見的情況來推導
  2. 你不應該叫普通情況下默認的構造函數,但一些專業。

我們去那裏:

template<typename T, bool = false> 
class B 
{ 
public: 
    B() { std::cout << "B common\n"; } 
    void yahoo() { std::cout << "yahoo!\n"; } 

protected: 
    struct internal_t; 
    B(internal_t*){} 

}; 

template <> 
struct B<double, false>: public B<double, true> 
{ 
    B(int, int):B<double, true>(0) { std::cout << "B double\n"; } 
}; 

int main(int argc,char *argv[]) 
{ 
    B<int> ib; 
    B<double> b(2,5); 

    ib.yahoo(); 
    b.yahoo(); 
} 
+0

爲什麼你在這裏使用struct而不是class? – user1504193

+0

@ user1504193,無論你使用'struct'還是'class',實際上並不重要。我使用了struct,因爲它允許省略'public:',因爲所有成員在'struct'中默認都是公共的。 – Lol4t0

7

好了,你不能真正做到這一點。如果您提供了一些不是doubleT,那麼編譯器將嘗試解析enable_if_c<false>::type,這將失敗,從而使整個類實例化失敗,而不僅僅是構造函數。

您可以使用C++ 11的默認函數模板參數來實現相同的功能。

下面的代碼實現,使用C++ 11版本的你在你的代碼中使用的boost特點:

#include <type_traits> 

template<typename T> 
class B { 
public: 
    // T == double -> this ctor can be used 
    template<typename U = T, class = typename std::enable_if<std::is_same<U, double>::value>::type> 
    B(int arg1, double arg2) {} 

    // Default ctor, available to every class. 
    B() {} 
}; 

int main(int argc,char *argv[]) 
{ 
    B<double> b_double(6, 6); 
    B<int> b_int; 

    // This line fails 
    //B<int> b_fails(6, 6); 
} 
+0

我可以用boost替換std ::如果我不使用C++ 11嗎? – user1504193

+1

不,因爲正如我在我的回答中所提到的,默認函數模板參數是C++ 11的一個特性。因此,使上述代碼工作的唯一方法是使用該功能。我的意思是,你可以使用boost :: enable_if,但你仍然需要C++ 11。 – mfontanini

+0

我希望我能給你+100。我花了數個小時尋找一種方法來實現這一目標,現在就是這樣。謝謝! –