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

При использовании следующего кода, если я пытаюсь преобразовать массив шаблонов в std :: string вместо компилятора, использующего ожидаемый метод преобразования std :: string, возникает проблема разрешения неоднозначности (так как он пытается вызвать массив методы конвертации):

#include <iostream>

template<typename TemplateItem>
class TestA
{
    public:
        TemplateItem Array[10];

        operator const TemplateItem *() const {return Array;}
        operator const std::string() const;
};

template<>
TestA<char>::operator const std::string() const
{
    std::string Temp("");
    return Temp;
}

int main()
{
    TestA<char> Test2;
    std::string Temp("Empty");
    Temp = Test2; //Ambiguity error. std::string or TemplateItem * ? 
    return 0;
}

Какую модификацию мне нужно внести в код, чтобы сделать так, чтобы код правильно и неявно разрешал функцию преобразования std :: string? Особенно с учетом того, что const TemplateItem * будет считаться массивом с нулевым символом в конце (что вряд ли будет).

Ответы [ 2 ]

5 голосов
/ 07 октября 2011

Во-первых, причина вашей двусмысленности: вы предоставляете и преобразование в char*, и преобразование в std::string const, и std::string любит их обоих.

Кстати, прежде чем перейти к вашему вопросу,const в operator std::string const когда-то была хорошей идеей, которую защищал, например, Скотт Мейерс, но в настоящее время это плохо: она мешает эффективному перемещению.

В любом случае, вопрос, просто избегайте неявных преобразований.Сделайте эти преобразования явными.Теперь я ответил, что в ответ на другой вопрос SO, и кто-то (я полагаю, что этот человек троллинг) заметил, что C ++ 98 не поддерживает операторы преобразования типа explicit.Это было достаточно верно, технически, но довольно глупо, как технический комментарий.Потому что вам не нужно использовать ключевое слово explicit (поддерживается C ++ 11), и это действительно не очень хороший способ сделать преобразования явными.Вместо этого просто name эти преобразования: используйте именованные функции-члены, а не операторы преобразования.


#include <iostream>

template<typename TemplateItem>
class TestA
{
    public:
        TemplateItem Array[10];

        TemplateItem  const* data() const { return Array; }
        std::string str() const;
};

template<>
std::string TestA<char>::str() const
{
    return "";
}

int main()
{
    TestA<char> test2;
    std::string temp( "Empty" );
    temp = test2.str();     // OK.
    temp = test2.data();    // Also OK.
}

Cheers & hth.

0 голосов
/ 07 октября 2011

Я добавлю, подумав об этом, вот рассуждения и что нужно сделать:

Оператор const TemplateItem * ();Должны быть удалены.

Почему?Никогда не будет экземпляра, в котором вы бы хотели неявное преобразование TestA (или любого класса шаблона) в массив TemplateItem с неизвестным размером - потому что это не имеет абсолютно никакой проверки границ (массив может иметь размер 1 или 10, 1000 или 0) иСкорее всего, произойдет сбой, если вызывающая функция или класс получат массив, не зная, какого он размера.

Если массив необходим, либо используйте оператор [] для прямых элементов, либо GetArray (который будет сигнализироватьпользователь намеревается передать массив неизвестной длины).

Сохранить оператор const std :: string.Код скомпилируется.Возможные проблемы с памятью предотвращены.

(Альф для его усилий был выбран в качестве «правильного» ответа, хотя это более логичный вариант)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...