2015-10-10 59 views
1

我想在C++中編寫一個簡單的函數模板,在該模板中打印出未知類型變量的值。問題是我無法弄清楚如何做到這一點,因爲變量可以是指針或原始類型。使用原始類型,我可以簡單地將值打印出來;但指針需要解除引用。打印未知類型變量的值?

下面的代碼給我一個錯誤:

#include <iostream> 
#include <type_traits> 

using namespace std; 

template<typename T> 
void foo(T someVar) { 
    if(std::is_fundamental<T>::value) { 
    cout << "It's primitive! \n" << someVar << endl; 
    } else { 
    cout << "It's a pointer! \n" << *someVar << endl; 
    } 
} 

int main(int argc, char **argv) { 
    int x = 5; 
    foo(x); 

    int *y = new int(); 
    *y = 5; 

    foo(y); 
    delete y; 

    return 0; 
} 

我編譯時得到的錯誤是:

test.cc: In function 'void foo(T) [with T = int]': 
test.cc:19:8: instantiated from here 
test.cc:13:5: error: invalid type argument of unary '*' (have 'int') 

它的抱怨,我試圖去參考基本類型從我第一次調用foo(),但這正是我使用if語句的原因:檢查它是否是原始的。我將如何去實施我想要做的事情?

回答

3

你需要做的是編寫2個模板化函數的版本。

template<typename T> 
void foo(T someVar) { 
    cout << "Assume it's primitive! \n" << someVar << endl; 
} 

template<typename T> 
void foo(T* pVar) { 
    cout << "This is a pointer! \n" << *pVar << endl; 
} 

編譯器將選擇指針版本,如果它工作,因爲它更具體。如果類型不是(原始)指針,它將默認爲第一個版本。

如果您需要智能指針取消引用,則可以進一步超載您的函數定義。

例如,

template<typename T> 
void foo(std::shared_ptr<T> pVar) { 
    cout << "This is a shared pointer! \n" << *pVar << endl; 
} 
+0

這些不是部分專業化,但實際上超載。如果你認爲他們是部分專業化的,[你可以感到驚訝](http://www.gotw.ca/publications/mill17.htm)。 – 5gon12eder

2

您需要額外的間接層。

#include <iostream> 

template < typename T > 
struct print_helper 
{ 
    static void 
    print(std::ostream& os, const T& value) 
    { 
    os << "The value is " << value << "\n"; 
    } 
}; 

template < typename T > 
struct print_helper< T * > 
{ 
    static void 
    print(std::ostream& os, const T *const pointer) 
    { 
    os << "The pointer points to " << *pointer << "\n"; 
    } 
}; 

template < typename T > 
void 
foo(T whatever) 
{ 
    print_helper<T>::print(std::cout, whatever); 
} 


int 
main() 
{ 
    const auto a = 42; 
    foo(a); 
    foo(&a); 
} 

輸出:

The value is 42 
The pointer points to 42 
1

編寫函數兩次:

struct Foo 
{ 
    template<typename T> 
    static void foo(T val) { 
     cout << "var: " << val << endl; 
    } 

    template<typename T> 
    static void foo(T* val) { 
     cout << "ptr: " << *val << endl; 
    } 
}; 

要撥打:

int x; 
int *y; 
Foo::foo(x); 
Foo::foo(y); 
1

一個解決方案我偏愛只是打印好聽點是編寫一個函數來執行去除encing。

template<typename T> T &deref(T &elem) { return elem; } 
template<typename T> T &deref(T *elem) { return *elem; } 

然後,你可以簡單地使用deref(value)任何地方,你不知道是否value將是一個指針,只要你不在乎它是。

template<typename T> 
void print(T t) { 
    std::cout << deref(t) << '\n'; 
}