2015-10-10 122 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'; 
}