Оператор перегрузки + = в шаблонном классе с метафункцией std :: enable_if

У меня есть строковый класс, реализованный в виде шаблона класса, например:

template <class T>
class HGStringBasic
{
//...
public:
//...
HGStringBasic& operator += (const T* rhs)
{
//...
}

template <class U, std::enable_if_t<std::is_same<U, char>::value>* = nullptr>
HGStringBasic& operator += (const U* rhs)
{
//...
}
//...
}

Код соответствует стандарту C ++ 11.
Целью было реализовать перегруженный оператор + = (const char), который используется только в том случае, если класс T шаблона, например, «wchar_t».

Я хотел бы знать, как я могу достичь того же результата, если компилятор не понимает C ++ 11.

ОБНОВИТЬ:
Извините, я новичок в stackoverlow и не видел, что мой код не был полностью показан в блоке кода. Я сейчас обновил мой код, снятый до сих пор.
Я также исправил ошибку в списке аргументов шаблона из оператора функции шаблона + = (), TartanLlama, вы абсолютно правы, is_same<T, char> должно быть is_same<U, char>,

1

Решение

Прежде всего, enable_if / is_same может быть легко реализовано в C ++ 2003. Например, у Boost они есть, или вы можете создать их самостоятельно — это хорошая практика.

Во-вторых, если вы не хотите использовать enable_if, вы можете просто предоставить специализацию myString для w_char. Чтобы уменьшить объем кода, поместите его в некоторый базовый класс, выведите myString из базового класса и обеспечьте специализацию базового класса.

1

Другие решения

enable_if не зависит от функциональности C ++ 11. Он был реализован задолго до C ++ 11 в библиотеке boost почти так же, как и сейчас. Вот возможная реализация, взятая из cppreference.com:

template<bool B, class T = void>
struct enable_if {};

template<class T>
struct enable_if<true, T> { typedef T type; };

Это прекрасно работало бы в C ++ до C ++ 11.

1

Прежде всего, ваш C ++ 11 делает не Работа. Если бы я попытался сделать:

myString<int> x;
x += new int(4);

Ваш operator+= не сможет скомпилировать. SFINAE применяется только в непосредственный контекст замещения — но T здесь не в непосредственном контексте, только U является. Таким образом, правильная вещь будет:

template <class U,
class _T=T,
class = std::enable_if_t<std::is_same<_T, char>::value>>
myString& operator += (const U* rhs);

Теперь вернемся к первоначальному вопросу. Как мы пишем выше в C ++ 03? Та же идея У нас просто не может быть аргументов шаблона по умолчанию. Но применяется тот же принцип: нам нужен сбой замещения в ближайшем контексте:

template <typename T, typename U, typename R>
struct allow_for_char;

template <typename U, typename R>
struct allow_for_char<char, U, R> { typedef R type; };

Который вы могли бы затем использовать, чтобы указать тип возвращаемого значения:

template <class U>
typename allow_for_char<T, U, myString&>::type
operator += (const U* rhs);
0

Теперь я понял, нет C ++ 11 и с уже известными метафункциями. Большое спасибо Барри за подсказку с указанием типа возврата.

Вот что я сделал:

#include <type_traits>

template <class _ElemT>
class HGStringBasic
{
public:
// Append char* or wchar_t* depending on specialization
HGStringBasic& operator += (const _ElemT* rhs)
{
return *this;
}

// Allow char* if specialization is wchar_t
template <class U>
typename std::enable_if<std::is_same<U, char>::value, HGStringBasic&>::type operator += (const U* rhs)
{
// Convert ansistring to widestring
return *this;
}

// Allow wchar_t* if specialization is char
template <class U>
typename std::enable_if<std::is_same<U, wchar_t>::value, HGStringBasic&>::type operator += (const U* rhs)
{
// Convert widestring to ansistring
return *this;
}
};
0