2017-06-11 37 views
0

我有這樣的代碼:在C++中,如何根據類中的參數返回不同的泛型?

template<class T1, class T2> 
class Pair 
{ 
private: 
    T1 first; 
    T2 second; 

public: 
    void SetFirst(T1 first) 
    { 
     this.first = first; 
    } 
    void SetSecond(T2 second) 
    { 
     this.second = second; 
    } 
    T1 GetFirst() 
    { 
     return first; 
    } 
    T2 GetSecond() 
    { 
     return second; 
    } 
}; 

我怎麼能實現兩個單獨的方法SetValue()GetValue(),而不是四個我有,這取決於參數決定哪一個泛型類型,應使用?例如,我認爲GetValue()方法可能需要1或2的int參數,並根據編號返回T1T2類型的變量。但我事先不知道返回類型,所以無論如何解決這個問題呢?

+3

如果你有getter和setter只是獲取和設置的東西,只是公開。 –

+0

我不確定,如果它能解決你的問題,但也許它爲你提供了一些啓發 - 尋找std :: tuple和std :: get。 – ArturFH

回答

0

C++是靜態類型的,所以給出的參數必須是模板參數,而不是函數參數。

雖然它看起來每個用戶都只有一個功能,但它確實是兩個。

template <int i = 1> auto GetValue() -> std::enable_if_t<i == 1, T1> { return first; } 
template <int i = 2> auto GetValue() -> std::enable_if_t<i == 2, T2> { return second; } 
template <int i = 1> auto SetValue(T1 x) -> std::enable_if_t<i == 1> { first = x; } 
template <int i = 2> auto SetValue(T2 x) -> std::enable_if_t<i == 2> { second = x; } 

我在返回類型上使用SFINAE刪除函數,除非模板參數是正確的。

1

不是一定要了解你想要什麼,你問不完全是,但...

我建議使用規定的包裝基類的如下

template <typename T> 
class wrap 
{ 
    private: 
     T elem; 

    public: 
     void set (T const & t) 
     { elem = t; } 

     T get() const 
     { return elem; } 
}; 

現在你的類可以定義爲

template <typename T1, typename T2> 
struct Pair : wrap<T1>, wrap<T2> 
{ 
    template <typename T> 
    void set (T const & t) 
    { wrap<T>::set(t); } 

    template <typename T> 
    T get() const 
    { return wrap<T>::get(); } 
}; 

,或者,如果你可以使用C++ 11和可變參數模板,如果你定義一個類型性狀getType獲得第N類型的列表中,

template <std::size_t I, typename, typename ... Ts> 
struct getType 
{ using type = typename getType<I-1U, Ts...>::type; }; 

template <typename T, typename ... Ts> 
struct getType<0U, T, Ts...> 
{ using type = T; }; 

可以定義一個更靈活的方式Pair如下

template <typename ... Ts> 
struct Pair : wrap<Ts>... 
{ 
    template <typename T> 
    void set (T const & t) 
    { wrap<T>::set(t); } 

    template <std::size_t N, typename T> 
    void set (T const & t) 
    { wrap<typename getType<N, Ts...>::type>::set(t); } 

    template <typename T> 
    T get() const 
    { return wrap<T>::get(); } 

    template <std::size_t N> 
    typename getType<N, Ts...>::type get() 
    { return wrap<typename getType<N, Ts...>::type>::get(); } 
}; 

現在的set()的參數可以選擇正確的基類和正確的基本元素

Pair<int, long> p; 

    p.set(0); // set the int elem 
    p.set(1L); // set the long elem 

否則,通過索引,您可以編寫

p.set<0U>(3); // set the 1st (int) elem 
    p.set<1U>(4); // set the 2nd (long) elem 

不幸的是,get()不接收參數,所以類型必須explicited(通過類型或通過指數)

p.get<int>(); // get the int elem value 
    p.get<long>(); // get the long elem value 

    p.get<0U>(); // get the 1st (int) elem value 
    p.get<1U>(); // get the 2nd (long) elem value 

顯然,這不工作的時候T1等於T2

以下是(C++ 11)全面工作示例

#include <iostream> 

template <std::size_t I, typename, typename ... Ts> 
struct getType 
{ using type = typename getType<I-1U, Ts...>::type; }; 

template <typename T, typename ... Ts> 
struct getType<0U, T, Ts...> 
{ using type = T; }; 

template <typename T> 
class wrap 
{ 
    private: 
     T elem; 

    public: 
     void set (T const & t) 
     { elem = t; } 

     T get() const 
     { return elem; } 
}; 

template <typename ... Ts> 
struct Pair : wrap<Ts>... 
{ 
    template <typename T> 
    void set (T const & t) 
    { wrap<T>::set(t); } 

    template <std::size_t N, typename T> 
    void set (T const & t) 
    { wrap<typename getType<N, Ts...>::type>::set(t); } 

    template <typename T> 
    T get() const 
    { return wrap<T>::get(); } 

    template <std::size_t N> 
    typename getType<N, Ts...>::type get() 
    { return wrap<typename getType<N, Ts...>::type>::get(); } 
}; 

int main() 
{ 
    //Pair<int, int> p; compilation error 
    Pair<int, long, long long> p; 

    p.set(0); 
    p.set(1L); 
    p.set(2LL); 

    std::cout << p.get<int>() << std::endl;  // print 0 
    std::cout << p.get<long>() << std::endl;  // print 1 
    std::cout << p.get<long long>() << std::endl; // print 2 

    p.set<0U>(3); 
    p.set<1U>(4); 
    p.set<2U>(5); 

    std::cout << p.get<0U>() << std::endl; // print 3 
    std::cout << p.get<1U>() << std::endl; // print 4 
    std::cout << p.get<2U>() << std::endl; // print 5 
} 
0

對於這種特殊情況,你一定要喜歡std::pairstd::tuple

你可以簡單地重載SetValue()(提供T1T2可以區分,如果不是你有一個編譯錯誤):

void SetValue(T1 x) 
{ first=x; } 

void SetValue(T2 x) 
{ second=x; } 

然後,編譯器找到任何呼叫的最佳匹配,即

Pair<int,double> p; 
p.SetValue(0); // sets p.first 
p.SetValue(0.0); // sets p.second 

GetValue(),你想要檢索哪個元素的信息不能從p.GetValue()這樣的東西推斷出來,所以你必須以某種方式提供它。有幾個選項,比如

template<typename T> 
std::enable_if_t<std::is_same<T,T1>,T> 
GetValue() const 
{ return first; } 

template<typename T> 
std::enable_if_t<std::is_same<T,T2>,T> 
GetValue() const 
{ return second; } 

使用像

auto a = p.GetValue<int>(); 
auto b = p.GetValue<double>(); 

但您最初的版本是不夠好。

相關問題