2017-02-23 82 views
0

我想創建一個模板類,它將實現一個不同的簽名回調,取決於它是否實例化一種或兩種。使用結構模板專用enable_if

struct NoIntermediate 
{ 
}; 

template<typename R, typename I> 
struct ParserCallbackSwitch 
{ 
    using type = std::function<bool(const std::string &, R&, I&)>; 
} 

template<typename R, typename I = NoIntermediate> 
class OtherClass 
{ 
public: 
    typedef ParserCallbackSwitch<R, I>::type ParserType; 

} 

現在我想添加代碼,這樣,如果實例時「OtherClass」,即ParserCallbackSwitch是沒有指定我:

template<typename R, typename I> 
struct ParserCallbackSwitch 
{ 
     using type = std::function<bool(const std::string &, R&)>; 
} 

請注意,在這種情況下ParserCallbackSwitch ::類型是一個函數只有兩個參數。

我希望能夠做到以下幾點:

OtherClass<int, float> p; // p::ParserType = std::function<bool(std::string &, int &, float &); 
OtherClass<int> q;  // q::ParserType = std::function<bool(std::string &, int &); 

我無法弄清楚如何對部分案件指定ParserCallbackSwitch當我是NoIntermediate型(沒有指定即我是)

解決方案:根據以下回應。這是我最終使用的代碼。

struct NoIntermediate {}; 

template<typename R, typename I = NoIntermediate> 
struct ParserCallbackSwitch 
{ 
    using type = std::function<bool(const std::string &, R&, I&)>; 
}; 

template<typename R> 
struct ParserCallbackSwitch<R, NoIntermediate> 
{ 
    using type = std::function<bool(const std::string &, R&)>; 
}; 

template<typename R, typename I = NoIntermediate> 
class OtherClass 
{ 
    public: 
    typedef ParserCallbackSwitch<R, I>::type ParserType; 
} 
+0

也許你想要[參數包](http://en.cppreference.com/w/cpp/language/parameter_pack)? –

回答

1

所以!你沒有正確地專注於模板。您正在定義碰巧具有相同名稱的兩個不相關的類模板。

有多種方法可以完成您的建議。這一個給最不專業的模板一個參數包。

#include <functional> 
#include <type_traits> 

template<typename... S> 
struct OtherClass; 

template<typename R, typename I> 
struct OtherClass<R, I> { 
    using ParserType = std::function<bool(std::string&, R&, I&)>; 
}; 

template<typename R> 
struct OtherClass<R> { 
    using ParserType = std::function<bool(std::string&, R&)>; 
}; 

int main(void) { 
    static_assert(std::is_same<OtherClass<int, float>::ParserType, 
          std::function<bool(std::string&, int&, 
               float&)>>(), 
       "Something wrong here."); 
    static_assert(std::is_same<OtherClass<int>::ParserType, 
          std::function<bool(std::string&, int&)>>(), 
       "Hmmmmmm."); 
    return 0; 
} 

您在參數中使用默認類型的想法也適用,但是您的語法略有偏差。這是看起來如何。

#include <functional> 
#include <type_traits> 

template<typename R, typename I = void> 
struct OtherClass { 
    using ParserType = std::function<bool(std::string&, R&, I&)>; 
}; 

template<typename R> 
struct OtherClass<R, void> { 
    using ParserType = std::function<bool(std::string&, R&)>; 
}; 

int main(void) { 
    static_assert(std::is_same<OtherClass<int, float>::ParserType, 
          std::function<bool(std::string&, int&, 
               float&)>>(), 
       "Something wrong here."); 
    static_assert(std::is_same<OtherClass<int>::ParserType, 
          std::function<bool(std::string&, int&)>>(), 
       "Hmmmmmm."); 
    return 0; 
} 
+0

關閉,但我不能使用void,因爲在代碼的另一部分,我使用它作爲函數的參數。如果我使用struct NoIntermediate {}的缺省值,第二個完美工作。 我會把我終於使用上面的代碼。謝謝! – bpeikes