C ++ ToString Member-функция и оператор Ostream << интеграция через шаблоны

StackOverflow https://stackoverflow.com/questions/5831353

Вопрос

Я новичок в разработчике C ++, и у меня есть вопрос о toString а также ostream Интеграция оператора через шаблоны. У меня такой код:

    struct MethodCheckerTypes{
        typedef unsigned char TrueType;
        typedef long FalseType;
    };
    template<typename T>struct HasToString{
        template<typename K>static typename MethodCheckerTypes::TrueType test(decltype(&K::toString));
        template<typename> static typename MethodCheckerTypes::FalseType test(...);
        static const bool value = sizeof(test<T>(0)) == sizeof(typename MethodCheckerTypes::TrueType);
        typedef decltype(test<T>(0)) ValueType;
    };

    template<typename T, typename K> struct IfDef{};
    template<> struct IfDef<typename MethodCheckerTypes::TrueType, ostream&>{
        typedef ostream& type;
    };

    class WithToString{
    public:
        string toString() const{
            return "hello";
        }
    };

    template<typename F, typename CharT, typename Traits> typename IfDef<typename HasToString<F>::ValueType, basic_ostream<CharT, Traits>&>::type operator<<(basic_ostream<CharT, Traits>& out, const F &ref){
        out<<ref.toString().c_str();
        return out;
    }
int main(int argc, char **argv){
    WithToString hasToString;
    cout<<hasToString<<endl;
    return 0;
}

Код был составлен без ошибок, а приложение выполнилось успешным. Хорошо ли использовать такой подход? Я хотел реализовать его без какой -либо помощи от повышения.

Это было полезно?

Решение

Подход к реализации operator<< сам по себе нормально. Но использование частей языка, которые вы не понимаете, является плохой практикой (я не верю, что новичок может написать такой код). У вас есть две альтернативы: для реализации toString Функция или перегрузка члена operator<<(std::ostream&, T). Анкет Последний подход позволяет использовать boost::lexical_cast Чтобы преобразовать объект в строку. Что касается меня, последний подход больше C ++ ISH, если вы можете что -то сделать без функции участника, лучше это сделать.

Другие советы

Я подошел к подходу, используя @begemoth Решение перегрузки оператора потока <<, а затем добавил удобный метод «Mixin» класса «Tostring» в тех случаях, когда вам нужна немедленная строка, например, для отладки:

template<typename T>
class ToString
{
public:
    std::string toString() const
    {
        return convertToString(static_cast<const T&>(*this));
    }
};

template<typename T>
inline std::string convertToString(const T& value)
{
    std::stringstream s;
    s << value;
    return s.str();
}

Затем вы можете унаследовать от этого класса в тех случаях, когда у вас есть оператор Ostream, и он даст вам метод Tostring в этом классе. Если вы используете BOOST, вы можете заменить реализацию конвертузирования с использованием lexical_cast:

template<typename T>
inline std::string convertToString(const T& value)
{
    return boost::lexical_cast<std::string>(value);
}

Если ваш класс предназначен для наследования и полиморфного доступа через указатели, то выше решения не будет работать, поскольку шаблоны привязаны во время компиляции, поэтому необходим другой подход. Следующий класс Mixin может использоваться вместо «Tostring» выше, где определяется виртуальный метод. Затем предоставляется удобный макрос для реализации виртуальной функции с точки зрения функции шаблона «преобразование». Это должно быть добавлено в класс тела каждого производного класса, поскольку он должен быть переопределен, и «этот» указатель статически связан с текущим типом.

class ToStringVirtual
{
public:
    virtual ~ToStringVirtual() {}
    virtual std::string toString() const = 0;
};

#define IMPLEMENT_ToStringVirtual public: std::string toString() const override { return convertToString(*this); }
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top