2016-07-10 2 views
2

По какой-то причине (ehm CUDA) Я использую printf() в своем коде на C++. Я хотел бы иметь возможность шаблона вокруг некоторых из этих применений, но для этого мне нужно получить спецификатор типа printf для разных типов. Предположим, мне нужно только это, чтобы работать для типов, которые действительно имеют соответствующие спецификаторы; и что я действительно не забочусь о научной и десятичной нотации и других подобных подробностях.Идиоматический способ получения спецификатора печати для типа?

Есть ли идиоматический способ сделать это, кроме таблицы поиска?

Примечание: Я бы хотел, чтобы это произошло во время компиляции, а не во время выполнения. Несмотря на то, что printf() сам разбирал его только во время выполнения.

ответ

3

Я хотел бы использовать что-то вроде этого:

template <typename T> struct PrintfSpecifier; 
#define TYPE_SPEC(type, spec) \ 
    template <> struct PrintfSpecifier<type>{static constexpr const char *value = spec;} 
TYPE_SPEC(int   , "%d"); 
TYPE_SPEC(unsigned int , "%u"); 
// More types here... 
#undef TYPE_SPEC 

И получить строку, которую вы можете использовать PrintfSpecifier<int>::value.


Если вы можете использовать C++ 14 и вас, как фантазии функций, есть более чистая альтернатива:

template <typename T> constexpr const char *printf_specifier = ""; 
#define TYPE_SPEC(type, spec) \ 
    template <> constexpr const char *printf_specifier<type> = spec; 
    TYPE_SPEC(int   , "%d"); 
TYPE_SPEC(unsigned int , "%u"); 
// More types here... 
#undef TYPE_SPEC 
+2

Нужно быть осторожным, потому что те, 'Const символ * 's не имеют привязки, поэтому, если у вас когда-либо есть функция, которая принимает const char * по ссылке и пытается передать это, вы получаете странные и бесполезные ошибки компоновщика. –

+0

@NirFriedman Хорошая мысль, но я не думаю, что это проблема. Константные ссылки отлично работают с ним, и в любом случае не константные ссылки не должны работать с константами. – HolyBlackCat

+0

Вы предлагаете в основном то, что я собирался сделать и надеясь избежать :-(Кроме того, я бы сделал этот макрос DEFINE_PRINTF_SPECIFIER, чтобы уменьшить вероятность столкновения имен, TYPE() скорее всего уже определен кем-то. – einpoklum