Поиск имени в NS параметра шаблона - можно что-то подобное придумать?
От: удусекшл  
Дата: 12.12.19 07:50
Оценка:
Здравствуйте!

Есть шаблонная функция:
template< typename StreamType >
void printSomething( StreamType s, const Something &something)
{
    s<<something.member;
    //...
}


У меня есть класс потока, совместимый со стандартным по интерфейсу, и я могу в эту функцию передавать как std::cout, так и myNS::myStream.

Теперь, я хочу вывести значение в 16ти-ричном виде. В std::iomanip есть манипулятор hex, есть он и myNS::iomanip, и синтаксически совместим со стандартным. Но я не могу его использовать, не указав его с полным именем NS. Мне нужно перед вызовом printSomething сделать using namespace std::iomanip, или using namespace myNS::iomanip. Но это делать не хочется.

Вариант — настроить поток на вывод hex'ов — не вариант — в функции printSomething я хочу вывести много полей структуры, и все — по-разному.

Есть ли какое-то решение?
Re: Поиск имени в NS параметра шаблона - можно что-то подобн
От: B0FEE664  
Дата: 12.12.19 09:57
Оценка: 2 (1)
Здравствуйте, удусекшл, Вы писали:

У>Теперь, я хочу вывести значение в 16ти-ричном виде. В std::iomanip есть манипулятор hex, есть он и myNS::iomanip, и синтаксически совместим со стандартным.

У>Есть ли какое-то решение?
Есть некрасивое и простое решение: можно добавить для myNS::myStream::hex манипулятора перегрузку оператора << для ostream класса и тогда можно использовать myNS::iomanip везде, но наверное есть другое, красивое решение.


PS Придумал:
template<class T> auto S_HEX                = std::hex;
template<>        auto S_HEX<myNS::iomanip> = myNS::iomanip::hex;

template< typename StreamType >
void printSomething( StreamType s, const Something &something)
{
    s << S_HEX<StreamType> << something.member;
    //...
}

Должно работать, но надо подумать над порядком инициализации глобальных переменных.
Кроме того, может быть на auto можно навесить constexpr и &
И каждый день — без права на ошибку...
Отредактировано 12.12.2019 10:27 B0FEE664 . Предыдущая версия .
Re[2]: Поиск имени в NS параметра шаблона - можно что-то подобн
От: удусекшл  
Дата: 12.12.19 10:56
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Здравствуйте, удусекшл, Вы писали:


У>>Теперь, я хочу вывести значение в 16ти-ричном виде. В std::iomanip есть манипулятор hex, есть он и myNS::iomanip, и синтаксически совместим со стандартным.

У>>Есть ли какое-то решение?
BFE>Есть некрасивое и простое решение: можно добавить для myNS::myStream::hex манипулятора перегрузку оператора << для ostream класса и тогда можно использовать myNS::iomanip везде, но наверное есть другое, красивое решение.

Ну, в принципе годно, спс


BFE>PS Придумал:

BFE>
BFE>template<class T> auto S_HEX                = std::hex;
BFE>template<>        auto S_HEX<myNS::iomanip> = myNS::iomanip::hex;

BFE>...
BFE>

BFE>Должно работать, но надо подумать над порядком инициализации глобальных переменных.
BFE>Кроме того, может быть на auto можно навесить constexpr и &

Спс. А это уже 17ый или еще 14ый?
Re[3]: Поиск имени в NS параметра шаблона - можно что-то подобн
От: B0FEE664  
Дата: 12.12.19 12:20
Оценка:
Здравствуйте, удусекшл, Вы писали:

У>Спс. А это уже 17ый или еще 14ый?

ЕМНИП это 14-ый (но я не уверен про поддержку специализации шаблонных переменных).
И каждый день — без права на ошибку...
Re: Поиск имени в NS параметра шаблона - можно что-то подобное придумать?
От: Videoman Россия https://hts.tv/
Дата: 12.12.19 14:05
Оценка: 1 (1)
Здравствуйте, удусекшл, Вы писали:

У>Есть ли какое-то решение?

Ну на С++17 можно сделать в лоб:
template< typename StreamType >
void printSomething( StreamType s, const Something &something)
{
    if constexpr (std::is_same_v<StreamType, Type1>)
    // Do output with type 1
    else if constexpr (std::is_same_v<StreamType, Type2>)
    // Do output with type 2
}
Re[4]: Поиск имени в NS параметра шаблона - можно что-то подобн
От: удусекшл  
Дата: 12.12.19 14:38
Оценка:
Здравствуйте, B0FEE664, Вы писали:


У>>Спс. А это уже 17ый или еще 14ый?

BFE>ЕМНИП это 14-ый (но я не уверен про поддержку специализации шаблонных переменных).

Хм. А как использовать шаблонные переменные без специализации? В чем смысл?
Re[5]: Поиск имени в NS параметра шаблона - можно что-то подобн
От: B0FEE664  
Дата: 12.12.19 16:09
Оценка:
Здравствуйте, удусекшл, Вы писали:

У>Хм. А как использовать шаблонные переменные без специализации? В чем смысл?


Например, если посмотреть на std::is_same_v, то можно увидеть, что это шаблонная переменная:
template< class T, class U >
inline constexpr bool is_same_v = is_same<T, U>::value;
И каждый день — без права на ошибку...
Re[2]: Поиск имени в NS параметра шаблона - можно что-то подобное придумать?
От: _NN_ www.nemerleweb.com
Дата: 16.12.19 17:32
Оценка:
Здравствуйте, Videoman, Вы писали:

V>Здравствуйте, удусекшл, Вы писали:


У>>Есть ли какое-то решение?

V>Ну на С++17 можно сделать в лоб:

Но лучше по старинке со специализацией потому как if constexpr — else требует компилируемость во всех ветках.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[3]: Поиск имени в NS параметра шаблона - можно что-то подобное придумать?
От: swingus  
Дата: 04.01.20 05:30
Оценка:
Как раз не требует.

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

_NN>Но лучше по старинке со специализацией потому как if constexpr — else требует компилируемость во всех ветках.
Re: Поиск имени в NS параметра шаблона - можно что-то подобное придумать?
От: swingus  
Дата: 04.01.20 05:36
Оценка: +1
Может я немного недопонял, но если сделать внутри функции printSomething() using namespace std::iomanip и using namespace myNS::iomanip, это будет не cool?

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

Мне нужно перед вызовом printSomething сделать using namespace std::iomanip, или using namespace myNS::iomanip. Но это делать не хочется.

У>Есть ли какое-то решение?
Re[2]: Поиск имени в NS параметра шаблона - можно что-то подобное придумать?
От: rg45 СССР  
Дата: 04.01.20 10:48
Оценка:
Здравствуйте, swingus, Вы писали:

S>Может я немного недопонял, но если сделать внутри функции printSomething() using namespace std::iomanip и using namespace myNS::iomanip, это будет не cool?


Если его манипулятор hex — это тоже функция, наподобие std::hex, то все будет работать — на правах двух перегрузок через ADL. А если его hex — это просто объект — экземпляр перечисления, например, то будет конфликт имен.

Ну и второй момент, я бы, все-таки, избегал using директив, даже в области видимости функций. Я бы предпочел using declarations: using std::hex, using std::dec, using myNS::iomanip::hex, etc.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[4]: Поиск имени в NS параметра шаблона - можно что-то подобное придумать?
От: _NN_ www.nemerleweb.com
Дата: 04.01.20 11:30
Оценка:
Здравствуйте, swingus, Вы писали:

S>Как раз не требует.


Note: the discarded statement can't be ill-formed for every possible specialization:

https://en.cppreference.com/w/cpp/language/if#Constexpr_If

Может когда нибудь изменят но пока так.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[5]: Поиск имени в NS параметра шаблона - можно что-то под
От: rg45 СССР  
Дата: 04.01.20 11:42
Оценка: +1
Здравствуйте, _NN_, Вы писали:


_NN>Note: the discarded statement can't be ill-formed for every possible specialization:

_NN>https://en.cppreference.com/w/cpp/language/if#Constexpr_If

Ты почитай ниже, там имеет значение dependent or not dependent (так же, как и в обычных шаблонах).

Если бы все всегда вычислялось, как бы могла работать функция, типа такой (пример оттуда же):

template <typename T>
auto get_value(T t) {
    if constexpr (std::is_pointer_v<T>)
        return *t; // deduces return type to int for T = int*
    else
        return t;  // deduces return type to int for T = int
}
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 04.01.2020 11:44 rg45 . Предыдущая версия .
Re[6]: Поиск имени в NS параметра шаблона - можно что-то под
От: _NN_ www.nemerleweb.com
Дата: 04.01.20 15:02
Оценка: +1
Здравствуйте, rg45, Вы писали:

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



_NN>>Note: the discarded statement can't be ill-formed for every possible specialization:

_NN>>https://en.cppreference.com/w/cpp/language/if#Constexpr_If

R>Ты почитай ниже, там имеет значение dependent or not dependent (так же, как и в обычных шаблонах).


В курсе. Ок. Я не достаточно точно написал.
В любом случае у enable_if есть преимущество SFINAE .
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[2]: Поиск имени в NS параметра шаблона - можно что-то подобн
От: Masterspline  
Дата: 05.01.20 04:52
Оценка: 1 (1)
BFE>template<class T> auto S_HEX = std::hex;
BFE>template<> auto S_HEX<myNS::iomanip> = myNS::iomanip::hex;

Я бы назвал это StreamTraits (по аналогии с iterator_traits и другими traits)
template<typename STREAM>
struct StreamTraits;

template<>
struct StreamTraits<std::basic_ostream<char>>
{
    constexpr static const auto hex = ::std::hex;
    constexpr static const auto dec = ::std::dec;
};

//template<>
//struct StreamTraits<myNS::myStream>
//{
//    constexpr static const auto hex = myNS::iomanip::hex;
//    constexpr static const auto dec = myNS::iomanip::hex;
//};

template< typename StreamType >
void printSomething( StreamType& s, const Something& something )
{
    s << StreamTraits<StreamType>::hex << "0x" << something.member << "\n";
    s << StreamTraits<StreamType>::dec << something.member << "\n";
    //...
}

  Работающий код
#include <iostream>

struct Something
{
    uint32_t member = 0x17;
};

template<typename STREAM>
struct StreamTraits;

template<>
struct StreamTraits<std::basic_ostream<char>>
{
    constexpr static const auto hex = ::std::hex;
    constexpr static const auto dec = ::std::dec;
};

//template<>
//struct StreamTraits<myNS::myStream>
//{
//    constexpr static const auto hex = myNS::iomanip::hex;
//    constexpr static const auto dec = myNS::iomanip::hex;
//};

template< typename StreamType >
void printSomething( StreamType& s, const Something& something )
{
    s << StreamTraits<StreamType>::hex << "0x" << something.member << "\n";
    s << StreamTraits<StreamType>::dec << something.member << "\n";
    //...
}

template< typename StreamType >
void printSomething2( StreamType& s )
{
    s << std::hex << 0x17 << "\n";
    s << std::dec << 0x17 << "\n";
    s << "===\n";
}

int main()
{
    printSomething2( std::cout );
    Something some;
    printSomething( std::cout, some );

    return 0;
}
Re[2]: Поиск имени в NS параметра шаблона - можно что-то подобное придумать?
От: удусекшл  
Дата: 09.01.20 09:55
Оценка:
Здравствуйте, swingus, Вы писали:

S>Может я немного недопонял, но если сделать внутри функции printSomething() using namespace std::iomanip и using namespace myNS::iomanip, это будет не cool?


В этом случае нужно подключать всё хидеры. А смысл шаблона в том, чтобы уйти от конкретных типов, и, в тч, ничего лишнего заранее не инклудить
Re[3]: Поиск имени в NS параметра шаблона - можно что-то под
От: rg45 СССР  
Дата: 09.01.20 11:49
Оценка:
Здравствуйте, удусекшл, Вы писали:

S>>Может я немного недопонял, но если сделать внутри функции printSomething() using namespace std::iomanip и using namespace myNS::iomanip, это будет не cool?


У>В этом случае нужно подключать всё хидеры. А смысл шаблона в том, чтобы уйти от конкретных типов, и, в тч, ничего лишнего заранее не инклудить


Ну так эта проблема существут в любом из предложенных решений. Вот
Автор: B0FEE664
Дата: 12.12.19
, например:

template<class T> auto S_HEX = std::hex;


Здесь std::hex не является зависимым именем и его объявление должно быть видимо в этой точке.

В то же время, я думаю, не будет большим преступлением сделать в собственном коде предварительные объявления некоторых сущностей, которые жестко зафиксированы в стандарте языка, чтоб не подключать заголовки без необходимости:

namespace std
{

class ios_base;

ios_base& dec(ios_base&);
ios_base& hex(ios_base&);
ios_base& oct(ios_base&);

} // namespace std
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 09.01.2020 11:52 rg45 . Предыдущая версия . Еще …
Отредактировано 09.01.2020 11:50 rg45 . Предыдущая версия .
Re[3]: Поиск имени в NS параметра шаблона - можно что-то подобное придумать?
От: swingus  
Дата: 17.01.20 05:37
Оценка:
В варианте using namespace xxx достаточно форвардно объявить namespace xxx {}.

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

У>В этом случае нужно подключать всё хидеры. А смысл шаблона в том, чтобы уйти от конкретных типов, и, в тч, ничего лишнего заранее не инклудить
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.