2015-10-20 3 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

Имейте в виду, что 'станд :: VECTOR' имеет более одного параметра шаблона. –

+0

Какова точка указателя-заглушки как второй аргумент? Ваши типы выводятся из первого аргумента. – SergeyA

+0

@SergeyA для реального? Как насчет std :: vector ? – omtcyfz

ответ

3

T от template<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

Это мне не понятно, почему вы используете два слоя функций ..

вы можете о ver foo для std::string и std::vector<T>.

#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 
Смежные вопросы