как лучше всего указать параметры форматирования?
От: _Winnie Россия C++.freerun
Дата: 06.10.05 13:44
Оценка:
Пишу свою библиотеку вывода текста.

В таком стиле:



struct vec3f_t
{
    vec3f_t(float x, float y, float z)
        :x(x), y(y), z(z)
    {
    }
    float x, y, z;
};

template <class T>
text_print::text_out_t<T> &operator <<(text_print::text_out_t<T> &to, const vec3f_t &in_vec)
{
    return to << '(' << in_vec.x <<',' << in_vec.y <<',' << in_vec.z <<')';
}

#include <iostream>

int main()
{
    char buf[1000];
    vec3f_t v(1, 2, 3);
    text_print::text_out(buf) << "hello" <<',' <<' ' <<"world" <<v << 1 <<1U <<-1ULL <<-1LL <<'\0';
    printf("[%s]\n", buf);
    
    std::string str;
    text_print::text_out(std::back_inserter(str)) << "hello" <<',' <<' ' <<"world" <<v;
    std::cout << str <<std::endl;


Подскажите, как с вашей точки зрения было бы удобней пользователю всего сделать форматирование?
Нужно устанавливать ширину поля (std::width), формат вывода числа double (std::fixed/std::scientific). [Еще что-то полезное?]

Вывод в стиле

std::cout
 << std::boolalpha << std::dec << std::fixed << std::hex << std::internal 
 << std::left << std::oct << std::right << std::scientific << std::showbase 
 << std::showpoint << std::showpos << std::skipws << std::unitbuf 
 << std::uppercase << std::adjutfield << std::basefield << std::floatfield 
 <<1;

мне кажется неудобным.

Хотелось бы как-то обойтись без префикса text_print:: перед каждым указанием формата.
пока что грезится кошмар вроде —

для типа double

<<left  (text_print::f(1.123, 4, 20))
<<center(text_print::e(1.123, 4, 20))
<<right (text_print::g(1.123, 4, 20))
  |                  | |      |  ^в поле шириной 20
  |                  | |      ^четыре знака после запятой
  |                  | ^что распечатываем
  |                  ^в "%g/%e/%f" формате
  ^выронять слева/посередине/справа. Префикса "text_print", так как koenig lookup
  
для целых:
<<sign("-", " ", "+", (text_print::x(12345, 10, 20)))
<<sign("-", "+", "+", (text_print::o(12345, 10, 20)))
<<sign("-", "", "",   (text_print::d(12345, 10, 20)))
  |                                  |      |   ^поле шириной 20
  |                                  |      ^дополнить до 10 символов нулями
  |                                  ^что печатаем
  ^как ставим знак перед отрицательным, нулем, положительным?

Но это же тоже кашмар!

Давайте сюда свои идеи как сделать лучше и удобней!

(Потом еще доделаю c-style printf строку, но хотелось бы удобного форматирования и в таком стиле.)
Правильно работающая программа — просто частный случай Undefined Behavior
Re: как лучше всего указать параметры форматирования?
От: srggal Украина  
Дата: 06.10.05 14:30
Оценка: 12 (1) +1
Здравствуйте, _Winnie, Вы писали:

Навскидку — предусмотреть возможность создания профилей(может можно еще как-то назвать) вывода, которые пользователь Вашей библиотеки сможет создать(определить) заблаговременно и использовать при выводе.

Под профилем я понимаю группировку параметров форматирования в одном месте(объекте)


MyDoubleFormater        dfmt( 4, 20 );

Или

MyDoubleFormater        dfmt;

dfmt << frac(4) << width( 20 ) << left;

std::cout << text_print::f( 1.123, dfmt );

Можно предусмотреть и такую возможность 

std::cout << dfmt << text_print::f(1.123);


ЗЫ Это все ИМХО чистейшей воды
... << RSDN@Home 1.1.4 stable rev. 510>>
Re: как лучше всего указать параметры форматирования?
От: Tuo_Bellas Россия  
Дата: 06.10.05 14:49
Оценка:
Здравствуйте, _Winnie, Вы писали:

_W>Пишу свою библиотеку вывода текста.


А чем плох, скажем, boost::format (+std::cout)?

Tuo_Bellas.
Re[2]: как лучше всего указать параметры форматирования?
От: _Winnie Россия C++.freerun
Дата: 06.10.05 17:29
Оценка: 8 (1)
Здравствуйте, Tuo_Bellas, Вы писали:

T_B>Здравствуйте, _Winnie, Вы писали:

_W>>Пишу свою библиотеку вывода текста.
T_B>А чем плох, скажем, boost::format (+std::cout)?
С++ lack for extensible, efficient, convenient and safe text format library.
Хочу все четыре.

Требование — no mallocs per frame. boost::format пролетает. и впечатляет. ОН УМУДРЯЕТСЯ ФОРМАТИРОВАТЬ СТРОКИ В 3 РАЗА МЕДЛЕННЕЙ ДАЖЕ ЧЕМ В .net, ЧЁРТ БЫ ЕГО ПОБРАЛ!!!


Здравствуйте, CyberZX, Вы писали:

CZX>>Кстати, строки и работа с текстом больная тема в С++. Не хватает быстрой, удобной и безопасной библиотеки.
CZX>тема вполне здоровая. всего хватает.

std::streams
безопасность
отлично!(compile-time)

удобство
плохо(как с std::ostring stream написать printf("%+10.4f %d %d %d %d %08x\n", 1.123f, 1, 2, 3, 4, address);?

эффективность
плохо

расширямость
отлично

boost::format

безопасность
хорошо (кидает исключения при неверном format string)

удобство
отлично

эффективность
ужасно

расширямость
отлично

printf family

безопасность
отвратительно.
(но хороший компилятор, вроде ICC/GCC делают предупреждения при неверном format string в compile-time, в отличие от boost::format).

удобство
хорошо
Большой жирный минус – нельзя вводить пользовательские типы

эффективность
хорошо. Если пишем не http сервер, жить можно.

расширямость
нету.




Здравствуйте, CyberZX, Вы писали:

CZX>boost::format, string_stream, boost::lexical_cast/istream
* _Winnie стошнило *
std :: streams — самая одиозная, неоднозначная, неэффективная часть стандартной библиотеки. boost::format и lexical_cast основаны на ней.

(шепотом) Ты же не вызываешь boost::formst/lexical_cast/stringstream на каждом кадре, например для вывода FPS или жизней?
Вот попробуй небольшое упражнение.

Напиши программу.

int main()
{
    std::string s = str(boost::format("%d") % 1);
}


Протрассируй в asm все иструкции с зажатой клавишей F11. Лично у меня терпения не хватило.
Попробуй протрассировать хотя бы только С/С++(с заходом во все функции). Потом отчитаешься, сколько минут на это ушло. И ты увидишь только часть этого отвратительного, жирного, ненужного, омерзительного кода.
Кстати, в Страуструпе тоже есть такое упражнение.

Даже в .NET скорость форматирования строки в 3 раза быстрей. Это ж надо умудриться так испоганить самый мощный и эффективный язык.
System::String *str = System::String::Format("{0}", __box(1));

* _Winnie пошел за другим тазиком *

std::fstream — единственная "буферизирующая" (смешно, нелепо и печально) в своем роде библиотека ввода/вывода, посимвольный ввод/вывод в которой работает медленней, чем жесткий диск! Обычно говорят, что скорость ввода лимитируется механикой жесткого диска. Мда. std::fstream показывает что навороченная типобезопасная абстрация может тормозить медленней, чем механический жесткий диск.
Дельфисты будут над нами смеяться! Програмисты на Йава и .НЕТ тоже.

Кстати, по ходу дела нашел того самого Шлемиля из статьи —
        for (i =0; i<n; i++)
        {
            strcat(outstr, va_arg(substr, char *));
        }

Правильно работающая программа — просто частный случай Undefined Behavior
Re[3]: как лучше всего указать параметры форматирования?
От: Cyberax Марс  
Дата: 06.10.05 18:35
Оценка: 1 (1)
_Winnie wrote:

> T_B>Здравствуйте, _Winnie, Вы писали:

> _W>>Пишу свою библиотеку вывода текста.
> T_B>А чем плох, скажем, boost::format (+std::cout)?
> С++ lack for extensible, *efficient*, convenient and safe text format
> library.
> Хочу все четыре.
> Требование — no mallocs per frame. boost::format пролетает. и
> впечатляет. ОН УМУДРЯЕТСЯ ФОРМАТИРОВАТЬ СТРОКИ В 3 РАЗА МЕДЛЕННЕЙ ДАЖЕ
> ЧЕМ В .net, ЧЁРТ БЫ ЕГО ПОБРАЛ!!!

Угу, меня это тоже поразило. В итоге написал свою простенькую библиотеку
форматирования, которая делает обычно всего одно динамическое
распределение памяти (а иногда даже ни одного ).

Выглядит примерно так (в этом примере, кстати, не будет ни одной аллокации):
std::ostream str;
...
str<<btl::fmt_begin()<<btl::fmt("Text %_1, %2, 
%3",11,12,13)<<btl::fmt_end();

В fmt_begin можно передавть разные опции.

> std::fstream — единственная "буферизирующая" (смешно, нелепо и

> печально) в своем роде библиотека ввода/вывода, посимвольный
> ввод/вывод в которой работает медленней, чем жесткий диск! Обычно
> говорят, что скорость ввода лимитируется механикой жесткого диска.
> Мда. std::fstream показывает что навороченная типобезопасная абстрация
> может тормозить медленней, чем *механический* жесткий диск.

Причем вся эта иерархия с bufstream'ами, iostream'ами и прочими
гадостями страшно неюзабельна и нерасширяема. Построеный на основе
потоков Boost.IOStreams — еще хуже.

> Дельфисты будут над нами смеяться! Програмисты на Йава и .НЕТ тоже.


Угу Даже потоки из wxWidgets сделаны лучше стандартных....

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re: как лучше всего указать параметры форматирования?
От: loki1000 Украина  
Дата: 07.10.05 05:52
Оценка:
Здравствуйте, _Winnie, Вы писали:

_W>Пишу свою библиотеку вывода текста.

Помнишь мой пример с fmt::combine<> на ГДР? Может, подойдет...

ЗЫ: на ГДР я _loki_
Re[3]: как лучше всего указать параметры форматирования?
От: ioni Россия  
Дата: 07.10.05 06:41
Оценка:
Здравствуйте, _Winnie, Вы писали:

в августовском c++ user journal
есть две статьи на тему реализации безопасного printf причем одна из них от Alexandrescu
правда вот про эфективность сказать ничего нельзя, надо тестировать
Re[4]: как лучше всего указать параметры форматирования?
От: Глеб Алексеев  
Дата: 07.10.05 10:08
Оценка: +1
Здравствуйте, Cyberax, Вы писали:


C>Причем вся эта иерархия с bufstream'ами, iostream'ами и прочими

C>гадостями страшно неюзабельна и нерасширяема. Построеный на основе
C>потоков Boost.IOStreams — еще хуже.

Вот тут не соглашусь ни разу. Когда наезжают за неэффективность и плохую диагностику ошибок — это за дело. Но расширяемость в стандартных потоках очень даже есть. Поддержку пользовательских типов добавить сложно? Нет, просто.
А недавно надо было сделать трассировку со стандартным потоковым интерфейсом, но на базе OutputDebugString, так это потребовало нарисовать свой streambuf с двумя переопределенными функциями, со всякими boiler-plate делами полэкрана кода, не так-то плохо, ИМХО.
Разделение iostream для форматирования, расширение перегрузкой операторов/streambuf для физического вывода, расширение через переопределение виртуальных функций — отличная идея. Мого быть, ее можно было чуть эффективнее реализовать.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[5]: как лучше всего указать параметры форматирования?
От: Cyberax Марс  
Дата: 07.10.05 10:34
Оценка:
Глеб Алексеев wrote:

> C>Причем вся эта иерархия с bufstream'ами, iostream'ами и прочими

> C>гадостями страшно неюзабельна и нерасширяема. Построеный на основе
> C>потоков Boost.IOStreams — еще хуже.
> Вот тут не соглашусь ни разу. Когда наезжают за неэффективность и
> плохую диагностику ошибок — это за дело. Но расширяемость в
> стандартных потоках очень даже есть.

Попробуйте на досуге с помощью стандартных потоков открыть файл с именем
в Юникоде.

> Поддержку пользовательских типов добавить сложно? Нет, просто.


Только в << и >>. Пожалуй это и есть единственное достоинство потоков.

> А недавно надо было сделать трассировку со стандартным потоковым

> интерфейсом, но на базе OutputDebugString, так это потребовало
> нарисовать свой streambuf с двумя переопределенными функциями, со
> всякими boiler-plate делами полэкрана кода, не так-то плохо, ИМХО.

В Java это делается написанием своего InputStream'а (три метода). В
wxWindows — точно так же.

> Разделение iostream для форматирования, расширение перегрузкой

> операторов/streambuf для физического вывода, расширение через
> переопределение виртуальных функций — отличная идея. Мого быть, ее
> можно было чуть эффективнее реализовать.

Вот streambuf — вообще уродливая идея. Не так это надо было делать...

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[6]: как лучше всего указать параметры форматирования?
От: Глеб Алексеев  
Дата: 07.10.05 10:47
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Попробуйте на досуге с помощью стандартных потоков открыть файл с именем

C>в Юникоде.
Да причем тут это? Мы вроде о дизайне говорили? Юникод у С++ вообще больное место, еще хуже потоков.

>> Поддержку пользовательских типов добавить сложно? Нет, просто.


C>Только в << и >>. Пожалуй это и есть единственное достоинство потоков.

Вот-вот, разделение форматирования и физического ввода-вывода, о чем я и говорил.

>> А недавно надо было сделать трассировку со стандартным потоковым

>> интерфейсом, но на базе OutputDebugString, так это потребовало
>> нарисовать свой streambuf с двумя переопределенными функциями, со
>> всякими boiler-plate делами полэкрана кода, не так-то плохо, ИМХО.
C>В Java это делается написанием своего InputStream'а (три метода). В
C>wxWindows — точно так же.
И полученный (OutputStream, я так понимаю) автоматически поддерживает все пользовательские типы (я не наезжаю, а спрашиваю)?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[7]: как лучше всего указать параметры форматирования?
От: Cyberax Марс  
Дата: 07.10.05 11:23
Оценка: 8 (1)
Глеб Алексеев wrote:

> C>Попробуйте на досуге с помощью стандартных потоков открыть файл с

> именем
> C>в Юникоде.
> Да причем тут это? Мы вроде о дизайне говорили? Юникод у С++ вообще
> больное место, еще хуже потоков.

А это ошибка дизайна. Почему-то авторы STL посчитали, что имя файла —
это не отдельная сущность (в Java и wxWidgets для имени файлов есть
специальнык классы).

Еще одна ошибка — отсутствие интероперабельности с Сшными потоками (то
есть FILE* из fstream'а мне не получить, а иногда это нужно).

> C>Только в << и >>. Пожалуй это и есть единственное достоинство потоков.

> Вот-вот, разделение форматирования и физического ввода-вывода, о чем я
> и говорил.

Но оно такое кривое... Идея с манипуляторами (которые, кстати, не
покрывают даже возможности printf!) — жутко неудобная.

> C>В Java это делается написанием своего InputStream'а (три метода). В

> C>wxWindows — точно так же.
> И полученный (OutputStream, я так понимаю) автоматически поддерживает
> все пользовательские типы (я не наезжаю, а спрашиваю)?

Нет, он поддерживает только бинарный ввод-вывод. Поверх него можно
построить TextInputStream (для текста), FilterInputStream (поддерживает
фильрацию) и т.п.

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[8]: как лучше всего указать параметры форматирования?
От: Глеб Алексеев  
Дата: 07.10.05 12:23
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>А это ошибка дизайна. Почему-то авторы STL посчитали, что имя файла —

C>это не отдельная сущность (в Java и wxWidgets для имени файлов есть
C>специальнык классы).
+1, но iostream начал жизнь как iostream.h так давно, что о Юникоде еще никто и не думал. Новые потоки совместимы со старыми.

C>Еще одна ошибка — отсутствие интероперабельности с Сшными потоками (то

C>есть FILE* из fstream'а мне не получить, а иногда это нужно).
Ну, это не фундаментальная ошибка, а недосмотр. Конструктор из FILE* есть, а назад получить нельзя, хотя добавить функцию никаких проблем не было.

>> И полученный (OutputStream, я так понимаю) автоматически поддерживает

>> все пользовательские типы (я не наезжаю, а спрашиваю)?
C>Нет, он поддерживает только бинарный ввод-вывод. Поверх него можно
C>построить TextInputStream (для текста), FilterInputStream (поддерживает
C>фильрацию) и т.п.
В этом случае при записи объекта в поток я должен знать, с каким потоком работаю, для независимости нужно наворачивать еще один абстрактный слой.
ИМХО, С++-ные потоки можно было довести до ума таким образом, чтобы
struct my_struct {
    int x;
    double y;
    std::string name;
};
stdfuture::ostream& operator<<(stdfuture::ostream& os, const my_struct ms) {
    return os << ms.x << ms.y << ms.name;
}
...
    cout << my_struct();
    ASNstream asn;
    asn << my_struct();
    XDRstream xdr;
    xdr << my_struct();

работало (в принципе, boost::serialization — шаг в эту сторону).
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[9]: как лучше всего указать параметры форматирования?
От: _Winnie Россия C++.freerun
Дата: 07.10.05 13:10
Оценка:
Так и не смог ничего придумать. Даже если дать возможность делать свои форматтеры, то самый удобный способ их задания — printf строка. Но это шаг в сторону от compile-time контролируемой безопасности. Пока делаю c-style форматирование.

Какие все-таки есть идеи для выражения форматирования, которое дает printf на кратком С++ ?
Правильно работающая программа — просто частный случай Undefined Behavior
Re[10]: как лучше всего указать параметры форматирования?
От: _Winnie Россия C++.freerun
Дата: 07.10.05 13:51
Оценка:
Здравствуйте, _Winnie, Вы писали:

printf("%.4f", vector3d)
Интересно, это должно применятся ко всем трем компонентам вектора, только к первой или быть ошибкой?
Правильно работающая программа — просто частный случай Undefined Behavior
Re[11]: как лучше всего указать параметры форматирования?
От: Centaur Россия  
Дата: 07.10.05 15:07
Оценка:
Здравствуйте, _Winnie, Вы писали:

_W>Здравствуйте, _Winnie, Вы писали:


_W>printf("%.4f", vector3d)

_W>Интересно, это должно применятся ко всем трем компонентам вектора, только к первой или быть ошибкой?

Мне вообще вся идея не нравится

У меня есть трёхмерный вектор. Трёхмерный вектор — это класс с тремя компонентами класса «координата». У меня есть форматтер для координат:
typedef double Coordinate;

class FormatCoordinate
{
private:
  Coordinate c;
public:
  explicit FormatCoordinate(Coordinate c)
  : c_(c)
  {}

  template <typename CharT, typename TraitsT>
  friend std::basic_ostream<CharT, TraitsT>& 
  operator<<(std::basic_ostream<CharT, TraitsT>& o, const FormatCoordinate& f)
  {
    boost::io::basic_ios_all_saver<CharT, TraitsT> saver(o);
    return o << std::setprecision(4) << f.c_;
  }
};


На основе этого форматтера я строю форматтер для вектора:
class Vector3d
{
private:
  Coordinate x_, y_, z_;
public:
  // skipped
  Coordinate x() const;
  Coordinate y() const;
  Coordinate z() const;
};

class FormatVector3d
{
private:
  const Vector3d& v_;
public:
  explicit FormatVector3d(const Vector3d& v)
  : v_(v), separator_(listSeparator)
  {}

  template <typename CharT, typename TraitsT>
  friend std::basic_ostream<CharT, TraitsT>& 
  operator<<(std::basic_ostream<CharT, TraitsT>& o, const FormatVector3d& f)
  {
    return o << "(" <<
      FormatCoordinate(f.v_.x()) << ", " <<
      FormatCoordinate(f.v_.y()) << ", " <<
      FormatCoordinate(f.v_.z()) << ")";
  }
};


А хотеть выводить Vector3d с разной шириной и разной точностью для каждой компоненты не надо. Это неизящно
Re[12]: как лучше всего указать параметры форматирования?
От: _Winnie Россия C++.freerun
Дата: 07.10.05 15:34
Оценка:
Здравствуйте, Centaur, Вы писали:

C>У меня есть трёхмерный вектор. Трёхмерный вектор — это класс с тремя компонентами класса «координата». У меня есть форматтер для координат:

C>
C>typedef double Coordinate;

C>class FormatCoordinate
C>{
C>private:
C>  Coordinate c;
C>public:
C>  explicit FormatCoordinate(Coordinate c)
C>  : c_(c)
C>  {}

C>  template <typename CharT, typename TraitsT>
C>  friend std::basic_ostream<CharT, TraitsT>& 
C>  operator<<(std::basic_ostream<CharT, TraitsT>& o, const FormatCoordinate& f)
C>  {
C>    boost::io::basic_ios_all_saver<CharT, TraitsT> saver(o);
C>    return o << std::setprecision(4) << f.c_;
C>  }
C>};
C>


C>На основе этого форматтера я строю форматтер для вектора:

C>
C>class Vector3d
C>{
C>private:
C>  Coordinate x_, y_, z_;
C>public:
C>  // skipped
C>  Coordinate x() const;
C>  Coordinate y() const;
C>  Coordinate z() const;
C>};

C>class FormatVector3d
C>{
C>private:
C>  const Vector3d& v_;
C>public:
C>  explicit FormatVector3d(const Vector3d& v)
C>  : v_(v), separator_(listSeparator)
C>  {}

C>  template <typename CharT, typename TraitsT>
C>  friend std::basic_ostream<CharT, TraitsT>& 
C>  operator<<(std::basic_ostream<CharT, TraitsT>& o, const FormatVector3d& f)
C>  {
C>    return o << "(" <<
C>      FormatCoordinate(f.v_.x()) << ", " <<
C>      FormatCoordinate(f.v_.y()) << ", " <<
C>      FormatCoordinate(f.v_.z()) << ")";
C>  }
C>};
C>


Ой, сколько телодвижений, что бы вывести 3 double

Хотелось бы что-то простое для пользователя — вроде

template <class T>
text_print::text_out_t<T> &operator <<(text_print::text_out_t<T> &to, const vec3f_t &in_vec)
{
    return to << '(' << in_vec.x <<',' << in_vec.y <<',' << in_vec.z <<')';
}

Это уже работает.

C>А хотеть выводить Vector3d с разной шириной и разной точностью для каждой компоненты не надо. Это неизящно

Я тоже так думаю
Я решил, что только спецификация ширины поля вывода должна применятся только ко всему объекту целиком, а остальное форматирование — для каждой подкомпоненты.
Правильно работающая программа — просто частный случай Undefined Behavior
Re[13]: как лучше всего указать параметры форматирования?
От: Centaur Россия  
Дата: 07.10.05 15:58
Оценка:
Здравствуйте, _Winnie, Вы писали:

_W>Здравствуйте, Centaur, Вы писали:


C>>У меня есть трёхмерный вектор. Трёхмерный вектор — это класс с тремя компонентами класса «координата». У меня есть форматтер для координат.

C>>На основе этого форматтера я строю форматтер для вектора:
C>>
C>>class Vector3d
C>>{
C>>private:
C>>  Coordinate x_, y_, z_;
C>>public:
C>>  // skipped
C>>  Coordinate x() const;
C>>  Coordinate y() const;
C>>  Coordinate z() const;
C>>};

C>>class FormatVector3d
C>>{
C>>private:
C>>  const Vector3d& v_;
C>>public:
C>>  explicit FormatVector3d(const Vector3d& v)
C>>  : v_(v), separator_(listSeparator)
C>>  {}

C>>  template <typename CharT, typename TraitsT>
C>>  friend std::basic_ostream<CharT, TraitsT>& 
C>>  operator<<(std::basic_ostream<CharT, TraitsT>& o, const FormatVector3d& f)
C>>  {
C>>    return o << "(" <<
C>>      FormatCoordinate(f.v_.x()) << ", " <<
C>>      FormatCoordinate(f.v_.y()) << ", " <<
C>>      FormatCoordinate(f.v_.z()) << ")";
C>>  }
C>>};
C>>


_W>Ой, сколько телодвижений, что бы вывести 3 double


Зато я таких форматтеров напишу три штуки — с форматированием в текст, в HTML и в MathML. И все будут выводить Vector3d в std::basic_ostream<CharT, TraitsT>. А operator<< всегда будет один.

_W>Хотелось бы что-то простое для пользователя — вроде


_W>
_W>template <class T>
_W>text_print::text_out_t<T> &operator <<(text_print::text_out_t<T> &to, const vec3f_t &in_vec)
_W>{
_W>    return to << '(' << in_vec.x <<',' << in_vec.y <<',' << in_vec.z <<')';
_W>}
_W>

_W>Это уже работает.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.