Как заставить компилятор использовать правильную специализацию шаблона? - PullRequest
2 голосов
/ 19 мая 2011

Рассмотрим следующую упрощенную версию моего кода. У меня есть шаблонный класс A, шаблонная функция Fill и специализация функции для работы с базовыми типами, такими как int или char, и другая специализация для работы с A:

#include <sstream>
#include <string>
#include <iostream>

template<size_t C>
class A
{
public:
    A & operator=(std::string v) { 
        data[0] ='a';
        return *this; 
    }
    char data[C];
};

template<typename T> T Fill(std::string value, T default_value);

// Specialization for A<C>
template<size_t C>
A<C> Fill(std::string value, A<C> default_value) 
{
    if (value.empty())
        return default_value;
    A<C> result;
    result = value;
    return result;
}

// Specialization for int, double, char, etc
template<typename T>
T Fill(std::string value, T default_value)
{   
    if (value.empty())
        return default_value;

    T result;
    std::istringstream(value) >> result;
    return result;
}

void main()
{
    int abc = Fill(/*Get a string somehow*/"123", 0); // OK

    A<10> def;
    def = std::string("111");
    A<10> a;
    a = Fill(/*Get a string somehow*/"abc", def);     // OK
}

Это прекрасно работает, хотя я поражен, что компилятору удается сопоставить параметр с правильной специализацией шаблона.

Проблема возникает с некоторыми typedef, которые упрощают использование A<x>. Вот упрощенная версия:

typedef A<12> A12;
...
A<12> def12;
def12 = std::string("12");

A12 a12;
a12 = Fill(/*Get a string somehow*/"xyz", def12);       // Not OK !

Компилятор не обнаруживает, что тип A12 на самом деле A<12>, и использует неправильную специализацию функции, которая не компилируется, поскольку istringstream не может выполнить синтаксический анализ с o perator>> в A.

Как я могу заставить его использовать правильную специализацию шаблона?

Ответы [ 3 ]

4 голосов
/ 19 мая 2011

Шаблон специализации не выводится через то, где вы присваиваете возвращаемое значение.Вам нужно явно создать правильную версию:

a12 = Fill<A<12> >("xyz", def);

(или что вам нужно ...)

1 голос
/ 19 мая 2011
typedef A<12> A12;
...
A12 a12;
a12 = Fill(/*Get a string somehow*/"xyz", def);       // Not OK !

В этом примере вы не показали нам тип def.Предполагая, что это то же самое, что и в предыдущем примере, а именно A<10>, это, безусловно, завершится ошибкой.

В вашем шаблоне тип второго параметра должен соответствовать типу возвращаемого значения.Попробуйте это:

typedef A<12> A12;
...
A12 a12;
A12 def12;
a12 = Fill(/*Get a string somehow*/"xyz", def12);       // OK !
0 голосов
/ 19 мая 2011

Компилятор не обнаруживает, что тип A12 действительно является A <12>, и использует неправильную специализацию функции

На самом деле, поскольку вы передаете A<12> def; в вашем примере (ошибка?), Должна быть выбрана правильная перегрузка (см. Мой комментарий к вопросу). Тот факт, что вы присваиваете результат A12 a;, не должен влиять на разрешение перегрузки.

Если вы имели в виду обратное (пропуск A12 и присвоение чему-либо), то это может быть недостатком компилятора. Это работает правильно здесь .

...