2016-08-03 2 views
1

Я пытаюсь изучить специализацию шаблона для языка C++, попадая в эту ситуацию, я не могу решить сам. Коды ниже:Отсутствует соответствующий вызов функции для специализации шаблона const char *

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

using namespace std; 
size_t count(const vector<string> &, const char* const &); 

template <typename T> 
size_t count(const vector<T>& v, const T& find) { 
    size_t c = 0; 
    for (auto ele : v) { 
    if (ele == find) 
     ++c; 
    } 
    return c; 
} 

template <> 
size_t count(const vector<double> &v, const double &find) { 
    size_t c = 0; 
    for (auto ele : v) { 
    if (abs(ele - find) < 0.0001) 
     ++c; 
    } 
    return c; 
} 

template <> 
size_t count(const vector<const char*> &v, const char* const &find) { 
    size_t c = 0; 
    for (auto ele : v) { 
    if (strcmp(ele, find) == 0) 
     ++c; 
    } 
    return c; 
} 

size_t count(const vector<string> &v, const char* const &find) { 
    size_t c = 0; 
    for (auto ele : v) { 
    if (strcmp(ele.c_str(), find) == 0) 
     ++c; 
    } 
    return c; 
} 

int main() { 
    vector<double> vd{0.1, 0.1, 0.2}; 
    cout << count(vd, 0.1) << endl; 
    vector<string> vs{"I", "you", "I"}; 
    cout << count(vs, "I") << endl; 
    vector<const char*> vc{"I", "you", "I"}; 
    cout << count(vc, "I") << endl; 
    return 0; 
} 

Компиляция этот код cout << count(vc, "I") << endl; сообщит об ошибке он не может найти вызов функции соответствия.

Однако я намеренно объявить специализацию для этого вызова функции, а именно template <> size_t count(const vector<const char*> &v, const char* const &find)

Что здесь не так?

спасибо.

+1

Ссылка на указатель в значительной степени бесполезна, если вы не должны изменять указатель, который вы не делаете (поэтому вы пометили его как постоянный указатель, я думаю, что делает его еще более бесполезным на самом деле). Просто объявите аргумент как простой 'const char *'. –

+2

Что касается вашей проблемы, когда вы спрашиваете о ошибках сборки, это помогает (много!), Если вы включаете фактические ошибки, которые вы получаете (в полном объеме, полный и неотредактированный) в теле вопроса. –

ответ

2

Способ специализации: первый вывод происходит против первичного шаблона, а затем рассматриваются любые специализации. Когда вы звоните count(vc, "I") мы выполняем вывод на

template <typename T> 
size_t count(const vector<T>& v, const T& find) 

, который будет выводить const char* первый T, но char[2] для второго T. Поскольку те не совпадают, вычет заканчивается неудачей. Не имеет значения, каковы ваши специализации (которые в любом случае ошибочны по той же причине).


Вместо специализации и с использованием тех же T в обоих местах, просто обеспечивают две перегрузки:

template <class Container, class ELem> 
size_t count(Container const& c, Elem const& elem); // uses operator== 

template <class Container, class UnaryPredicate> 
size_t count(Container const& c, UnaryPredicate f); // uses f() 

Таким образом, вы можете написать:

count(vd, [](double d){return abs(d-0.1) < 0.00001;}); 
count(vc, [](const char* p){ return strcmp(p, "I") == 0; }); 

без добавления дублирования.

+1

Или, знаете, ['std :: count_if'] (http://en.cppreference.com/w/cpp/algorithm/count) –

+0

Благодарим за ответ. В этом случае, почему строковый литерал C-стиля не может быть выведен как тип 'const char *'. В выводе типа шаблона допускается преобразование массива в указатель и неявно. –

+0

@ShaunZiqinRong Потому что преобразование приходит позже. Фактический тип строкового литерала - 'const char [n]', и это то, что использует шаблон. – NathanOliver

Смежные вопросы