Форум программистов, компьютерный форум CyberForum.ru

Простое создание строки из объектов разных типов данных - C++

Восстановить пароль Регистрация
 
orange_fox
 Аватар для orange_fox
34 / 34 / 6
Регистрация: 06.04.2014
Сообщений: 189
26.07.2014, 23:40     Простое создание строки из объектов разных типов данных #1
Всем доброго времени суток. Создал класс, который (по моему мнению) сделает более удобным создание строк и их передачу в функции, принимающие строки. Посоветуйте, как можно (если нужно) его улучшить.

Пример использования
C++
1
2
3
4
string num = mkstr() << 15 //число в строку
//передача строки в функцию
int a = rand()%100
ofstream fout(mkstr() << "file" << a << ".txt");
Исходный код
Кликните здесь для просмотра всего текста

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class mkstr
{
public:
    template <class T>
    mkstr& operator<<(const T& data)
    {
        ss << data;
        return *this;
    }
    operator string()
    {
        return ss.str();
    }
private:
    stringstream ss;
};
Лучшие ответы (1)
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Jupiter
Каратель
Эксперт C++
6543 / 3963 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
27.07.2014, 07:38     Простое создание строки из объектов разных типов данных #2
C++
1
2
3
4
operator string() const
{
    return ss.str();
}
MasterOfOrion
Заблокирован
27.07.2014, 07:50     Простое создание строки из объектов разных типов данных #3
А в чём смысл данного извращения? Какой функциональности не хватает?
0x10
2426 / 1598 / 232
Регистрация: 24.11.2012
Сообщений: 3,919
27.07.2014, 10:30     Простое создание строки из объектов разных типов данных #4
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от MasterOfOrion Посмотреть сообщение
А в чём смысл данного извращения? Какой функциональности не хватает?
Функциональности стандартной библиотеки вполне хватает, просто иногда хочется то же самое записать более лаконично.
Пример приведен в первом же посте - конкатенацией строк получить имя файла.
Обычно для этого нужно либо создавать объект std::stringstream, что к третьему разу уже надоедает, либо каждый объект приводить к строке вызовом std::to_string, что тоже громоздко.
В общем, это шорткат для удобства.

Но реализация не кажется такой уж выигрышной. Основной вопрос: а зачем нам нужен класс? Да еще и с оператором приведения к std::string, что добавляет неявного поведения. Подразумевается ли создание его невременних объектов? Если да, то преимуществ перед std::stringstream никаких. Если нет, то это повод задуматься о написании обычной функции.

Пример:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <sstream>
 
template <class T>
void to_string_impl(std::ostream& os, T&& value) {
  os << value;
}
 
template <class T, class... Args>
void to_string_impl(std::ostream& os, T&& value, Args&&... args) {
  to_string_impl(os, value);
  to_string_impl(os, args...);
}
 
template <class... Args>
std::string to_string(Args&&... args) {
  std::stringstream ss;
  to_string_impl(ss, args...);
  return ss.str();
}
 
int main() {
  std::cout << to_string(1, 2, 3.14, "abc");
}
Voivoid
 Аватар для Voivoid
580 / 256 / 12
Регистрация: 31.03.2013
Сообщений: 1,284
27.07.2014, 10:47     Простое создание строки из объектов разных типов данных #5
Цитата Сообщение от 0x10 Посмотреть сообщение
Пример:
Тогда уж boost::format
0x10
2426 / 1598 / 232
Регистрация: 24.11.2012
Сообщений: 3,919
27.07.2014, 10:50     Простое создание строки из объектов разных типов данных #6
Цитата Сообщение от Voivoid Посмотреть сообщение
Тогда уж boost::format
Хорош когда есть шаблон строки с плейсхолдерами. В примере - простая конкатенация строк. Конкретной ситуации когда нужен был именно такой функционал, правда, не вспомню, но как минимум тут не происходит парсинга шаблона строки.
orange_fox
 Аватар для orange_fox
34 / 34 / 6
Регистрация: 06.04.2014
Сообщений: 189
27.07.2014, 14:16  [ТС]     Простое создание строки из объектов разных типов данных #7
0x10, Спасибо. А теперь можешь объяснить как это устроено и как работает? А то, мой пример с классом для меня очевиден(почти), а тут что-то страшное
0x10
2426 / 1598 / 232
Регистрация: 24.11.2012
Сообщений: 3,919
27.07.2014, 14:53     Простое создание строки из объектов разных типов данных #8
Цитата Сообщение от orange_fox Посмотреть сообщение
А теперь можешь объяснить как это устроено и как работает?
Сия техника есть великая темная магия. И магию эту мне настолько редко приходится использовать в реальных проектах, что сразу же отсылка:
Страуструп, The C++ Programming Language, 4th edition,
Part III: Abstraction Mechanisms
28. Metaprogramming
* Variadic Templates

Попытаюсь коротко описать в декларативном стиле что тут зачем.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
#include <sstream>
 
template <class T>
void to_string_impl(std::ostream& os, T&& value) {
  os << value;
}
 
// Функция будет вызвана если в передаваемом пакете 2 или более аргументов.
// Первый из них связывается с value, остальные остаются в args.
template <class T, class... Args>
void to_string_impl(std::ostream& os, T&& value, Args&&... args) {
  // Обрабатываем первый аргумент
  to_string_impl(os, std::forward<T>(value)); // Добавил условный каст std::forward
  // Обрабатываем остальные. Когда в пакете останется единственный аргумент,
  // будет вызвана функция void to_string_impl(std::ostream& os, T&& value)
  to_string_impl(os, args...);
}
 
// Аргумент функции - пакет параметров любого типа.
// Функция может быть вызвана для любого количества аргументов.
template <class... Args>
std::string to_string(Args&&... args) {
  std::stringstream ss;
  to_string_impl(ss, args...);
  return ss.str();
}
 
int main() {
  std::cout << to_string(1, 2, 3.14, "abc");
}
Интуитивно это понятно всем, кто хоть немного трогал функциональные языки. Классический рекурсивный обход списка: чтобы обработать весь список, нужно обработать сначала его первый элемент, а заетем остальные. Условие завершение рекурсивого вызова - когда в списке не осталось элементов.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
27.07.2014, 15:14     Простое создание строки из объектов разных типов данных
Еще ссылки по теме:

C++ Не считает произведение разных типов данных
C++ Определить наибольшее из 3 чисел для данных разных типов
C++ Функция swap перестановки значений двух переменных для данных разных типов. Используйте template

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
0x10
2426 / 1598 / 232
Регистрация: 24.11.2012
Сообщений: 3,919
27.07.2014, 15:14     Простое создание строки из объектов разных типов данных #9
DiffEreD, На самом деле, пост зря удалил. В одном-то месте я вспомнил про std::forward, в остальных как-то не подумал.

Добавлено через 9 минут
В общем, если хочется оформить как библиотечку, можно как-то так:
Код
`-- Shortcut
    |-- Details
    |   `-- to_string.h
    `-- to_string.h
Shortcut/to_string.h

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#pragma once
 
#include <sstream>
#include <string>
 
#include "Details/to_string.h"
 
namespace Shortcut {
 
template<class... Args>
std::string to_string(Args&&... args) {
  std::ostringstream oss;
  Details::to_string_impl(oss, std::forward<Args>(args)...);
  return oss.str();
}
 
} // namespace Shortcut

Shortcut/Details/to_string.h

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#pragma once
 
#include <string>
 
namespace Shortcut {
namespace Details {
 
template <class T>
void to_string_impl(std::ostream& os, T&& item) {
  os << item;
}
 
template <class T, class... Args>
void to_string_impl(std::ostream& os, T&& item, Args&&... args) {
  to_string_impl(os, std::forward<T>(item));
  to_string_impl(os, std::forward<Args>(args)...);
}
 
} // namespace Details
} // namespace Shortcut


Понятно, что до универсальности тут далеко - достаточно вспомнить, что на std::string свет клином не сошелся, но просто лень писать. Т.е. тип символов тоже было бы неплохо параметризовать.
Yandex
Объявления
27.07.2014, 15:14     Простое создание строки из объектов разных типов данных
Ответ Создать тему
Опции темы

Текущее время: 05:18. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru