2016-04-28 160 views
6

假設我有這樣的:有一個模板參數可以是指針類型或非指針類型

template <class T> 
void do_something(T t){ 
    pass_it_somewhere(t); 
    t->do_something(); 
} 

現在T被允許成爲一個指針 - 或非指針類型將是有益的。函數do_something(...)基本上可以處理指針和非指針,除了t->do_something()。對於指針,我需要一個->,對於非指針,我需要一個.來訪問成員。

有沒有辦法讓T接受指針非指針?

回答

9

你可以如下創建取消引用機制:

template<typename T> 
std::enable_if_t<std::is_pointer<T>::value, std::remove_pointer_t<T>&> dereference(T& t) { 
    return *t; 
} 

template<typename T> 
std::enable_if_t<!std::is_pointer<T>::value, T&> dereference(T& t) { 
    return t; 
} 

,並用它在你的函數爲:

template <class T> 
void do_something(T t){ 
    pass_it_somewhere(dereference(t)); 
    dereference(t).do_something(); 
} 

Live Demo

這樣,你必須只用混凝土做版本T

+1

我認爲這是最好的答案,因爲它會產生非常可讀和簡潔的代碼。謝謝 :-) – Michael

7

Soultion 1只

使用模板特:

template <class T> 
void do_something(T t){ 
    pass_it_somewhere(t); 
    t.do_something(); 
} 

template <class T> 
void do_something(T* t){ 
    pass_it_somewhere(t);  
    t->do_something(); 
} 

溶液2

在T級添加一個用戶定義的指針操作:

class A 
{ 
public: 
    void do_something() const {}   
    const A* operator->() const { return this; } 
}; 

template <class T> 
void do_something(T t){ 
    pass_it_somewhere(t);  
    t->do_something(); 
} 
+0

這是一個解決方案,但在我的情況下會非常不方便... – Michael

+4

s/specialize/overload – Barry

2

又一個解決方案:標籤調度。

namespace detail { 
    struct tag_value {}; 
    struct tag_ptr {}; 

    template <bool T> struct dispatch  { using type = tag_value; }; 
    template <>  struct dispatch<true> { using type = tag_ptr; }; 

    template <class T> 
    void do_call(T v, tag_value) 
    { 
     v.call(); 
    } 

    template <class T> 
    void do_call(T ptr, tag_ptr) 
    { 
     ptr->call(); 
    } 
} 

那麼你的函數變爲:

template <class T> 
void do_something(T unknown) 
{ 
    do_call(unknown, 
       typename detail::dispatch<std::is_pointer<T>::value>::type{}); 

    // found by ADL 

} 

Live Example

相關問題