2015-10-20 140 views
0

我想調用template<typename T> foo(T x)並手動處理這些情況:T = std::vector<U>,T = std::string,T =任何其他情況。模板專業化問題

這裏是我寫爲:

#include <iostream> 
#include <vector> 
#include <string> 

template<typename T> void foo_impl(const std::string &data, std::string *) { 
    std::cout << "foo for std::string called\n"; 
} 

template<typename T> void foo_impl(const T &data, T *) { 
    std::cout << "foo for general types called\n"; 
} 

template<typename T> void foo_impl(const std::vector<T> &data, std::vector<T> *) { 
    std::cout << "foo for std::vector<T> called\n"; 
} 

template<typename T> void foo(const T &data) { 
    foo_impl(data, static_cast<T*>(nullptr)); 
} 


int main() { 
    int i = 1; 
    foo(i); 
    std::vector<int> a = {0, 1}; 
    foo(a); 
    std::string s = "abcd"; 
    foo<std::string>(s); 
    return 0; 
} 

然而,foo(std::string x)被稱爲萬一「T是任何其他類型的」。我如何處理它?

+1

注意,'的std :: VECTOR'有不止一個模板參數。 –

+0

作爲第二個參數的虛擬指針的作用是什麼?你的類型是從第一個參數中推導出來的。 – SergeyA

+0

@SergeyA真的嗎?怎麼樣std :: vector ? – omtcyfz

回答

3

Ttemplate<typename T> void foo_impl(const std::string &data, std::string *)是不可扣除的(也就是說,它沒有用在函數的參數列表中),因此它不被視爲可行的過載。

您可以刪除template<typename T>部分,使這個重載一個非模板:

void foo_impl(const std::string &data, std::string *) { 
    std::cout << "foo for std::string called\n"; 
} 
+0

啊,你是對的!我的錯!非常感謝! – omtcyfz

4

模板:

template<typename T> void foo(const T &data) { 
    std::cout << "foo for general types called\n"; 
} 

下面是一個專業化:

template<> void foo<>(const std::string &data) { 
    std::cout << "foo for std::string called\n"; 
} 

,但簡單過載似乎更合適:

void foo(const std::string &data) { 
    std::cout << "foo for std::string called\n"; 
} 

如偏特是不可能的功能時,必須做出過載vector情況:

template<typename T, typename Alloc> void foo(const std::vector<T, Alloc> &data) { 
    std::cout << "foo for std::vector<T, Alloc> called\n"; 
} 

一種替代方法是轉發到類/結構可以是(部分地)專門:

template <typename T> 
struct foo_impl { 
    void operator (const T&) const 
    { 
     std::cout << "foo for general types called\n"; 
    } 
}; 

// specialization for std::string 
template <> 
struct foo_impl<std::string> 
{ 
    void operator (const T&) const 
    { 
     std::cout << "foo for std::string called\n"; 
    } 
}; 

// partial specialization for std::vector 
template <typename T, typename A> 
struct foo_impl<std::vector<T, A>> 
{ 
    void operator (const std::vector<T, A>&) const 
    { 
     std::cout << "foo for std::vector<T, A> called\n"; 
    } 
}; 

template <typename T> 
void foo(const T& t) 
{ 
    foo_impl<T>{}(t); 
} 
2

爲什麼你正在使用的功能兩層目前尚不清楚對我..

您可以Ø對於std::stringstd::vector<T>來說,版本foo

#include <iostream> 
#include <vector> 
#include <string> 

template<typename T> void foo(const T &data) { 
    std::cout << "foo for general types called\n"; 
} 

template <typename T> void foo(const std::vector<T> &data) { 
    std::cout << "foo for std::vector<T> called\n"; 
} 

void foo(const std::string &data) { 
    std::cout << "foo for std::string called\n"; 
} 

int main() { 
    int i = 1; 
    foo(i); 
    std::vector<int> a = {0, 1}; 
    foo(a); 
    std::string s = "abcd"; 
    foo(s); 
    return 0; 
} 

輸出:

foo for general types called 
foo for std::vector<T> called 
foo for std::string called