Перегрузка функции-члена / проблема специализации шаблона - PullRequest
4 голосов
/ 05 января 2011

Я пытался вызвать перегруженную функцию-член table::scan_index(std::string, ...), но безуспешно. Для ясности я вычеркнул весь не относящийся к делу код.

У меня есть класс с именем table, который имеет перегруженную / шаблонную функцию-член с именем scan_index() для обработки строк как особого случая.

class table : boost::noncopyable
{
public:
    template <typename T>
    void scan_index(T val, std::function<bool (uint recno, T val)> callback) {
        // code
    }

    void scan_index(std::string val, std::function<bool (uint recno, std::string val)> callback) {
        // code
    }
};

Тогда существует класс hitlist, который имеет ряд шаблонных функций-членов, которые вызывают table::scan_index(T, ...)

class hitlist {
public:
    template <typename T>
    void eq(uint fieldno, T value) {
        table* index_table = db.get_index_table(fieldno);
        // code
        index_table->scan_index<T>(value, [&](uint recno, T n)->bool {
            // code
        });
    }
};

И, наконец, код, с которого все начинается:

hitlist hl;
// code
hl.eq<std::string>(*fieldno, p1.to_string());

Проблема в том, что вместо вызова table::scan_index(std::string, ...) он вызывает шаблонную версию. Я попытался использовать как перегрузку (как показано выше), так и шаблон специализированной функции (ниже), но, похоже, ничего не работает. После нескольких часов просмотра этого кода я чувствую, что упускаю что-то очевидное. Есть идеи?

    template <>
    void scan_index<std::string>(std::string val, std::function<bool (uint recno, std::string val)> callback) {
        // code
    }

Обновление: Я уронил украшение <T> из звонка scan_index(). В результате вызовы со строковым параметром компилируются просто отлично, но вызовы с другими типами (например, double) приводят к следующей ошибке:

cannot convert parameter 1 from 'double' to 'std::string'

Итак, я вернулся к использованию шаблонной специализации. Теперь я получаю эту ошибку:

error C2784: 'void table::scan_index(T,std::tr1::function<bool(uint,T)>)' :
  could not deduce template argument for 'std::tr1::function<bool(uint,T)>'
  from '`anonymous-namespace'::<lambda5>'

К вашему сведению: я использую VC ++ 10.0

Решение: Я исправил эту проблему, убрав шаблонную функцию scan_index() из класса table и просто написав четыре перегруженные функции (три из которых идентичны, за исключением сигнатуры). К счастью, все они довольно короткие (менее десяти строк), так что все не так плохо.

Ответы [ 4 ]

7 голосов
/ 05 января 2011

Вы явно вызываете шаблонного члена здесь:

index_table->scan_index<T>(value, [&](uint recno, T n)...

Поскольку value является параметром шаблона, вы должны заменить его на:

index_table->scan_index(value, [&](uint recno, T n)...
3 голосов
/ 05 января 2011

Вы не должны явно указывать аргумент шаблона - вы должны оставить его для вывода аргумента шаблона и разрешения перегрузки. Это должно позволить перегрузке, которую вы разместили в самом оригинальном коде, быть обнаруженной и использованной.

1 голос
/ 05 января 2011

Разве специализация шаблона не может быть чем-то вроде:

template <typename T>
void scan_index(T val, std::function<bool (uint recno, T val)> callback) {
    // code
}
template <>
void scan_index(std::string val, std::function<bool (uint recno, std::string val)> callback) {
    // code
}

Таким образом, компилятор C ++ распознает, что scan_index имеет специализацию, а не ищет перегруженный метод.И я считаю, что если вы хотите, чтобы это было так, как вы можете кодировать, вам, вероятно, следует поместить специальный шаблон перед шаблоном, например:

    void scan_index(std::string val, std::function<bool (uint recno, std::string val)> callback) {
        // code
    }
template <typename T>
    void scan_index(T val, std::function<bool (uint recno, T val)> callback) {
        // code
    }
1 голос
/ 05 января 2011

подготовил этот упрощенный тест (извините, у меня нет atm компилятора C ++ 0x):

class table
{
public:
    template <typename T>
    void scan_index(T val) {
        std::cout << "template\n";
    }

    template <>
    void scan_index<int>(int val) {
        std::cout << "specialization\n";
    }

    void scan_index(int val) {
        std::cout << "overloaded\n";
    }
};

class hitlist {
public:
    template <typename T>
    void eq(T value) {
        table tbl;
        tbl.scan_index<T>(value);
    }
};

int main(int argc, char* argv[])
{
    int i = 0;
    hitlist hl;
    hl.eq(i);
    return 0;
}

вывод "специализация" (VC9). Это потому, что hitlist :: eq явно использует версию шаблона, поэтому будет рассматриваться только специализация шаблона. если вы измените tbl.scan_index<T>(value); на tbl.scan_index(value);, будет вызвана перегруженная версия.

tbh Я не знаю, почему ваша специализация шаблона не работает, возможно, из-за лямбды, не полной поддержки C ++ 0x? какой компилятор?

...