C ++ шаблон T, обнаруживающий Тип является формой строки - PullRequest
2 голосов
/ 17 января 2012

У меня есть шаблонная функция в C ++, которая в основном записывает значения в файл XML, для целей проверки я хочу выписать тип переменной, а также ее значение. В настоящее время я использую typeid(T).name(), который отлично работает для int, double и т. Д., Но я хочу специальный случай для char массивов и std::string, чтобы он всегда записывал "строку" или что-то более значимое, чем:

class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >

или

char const  [2]

Любые идеи о том, как я могу сделать это элегантно?

Мой код (вырублен) выглядит так (не только функция является шаблоном)

  template <typename T> bool SetValue(const std::string &sectionName, const std::string &valueName, const T &value)
  {
      myXMl->AddAttribute(TYPE_DEF,typeid(T).name());
      return true;
  }

Ответы [ 2 ]

10 голосов
/ 17 января 2012

Вы можете использовать класс черт для этого:

template<class T>
class type_name {
public:
    static std::string get() { return typeid(T).name(); }
};

Этот шаблон реализует регистр по умолчанию. Теперь вы можете специализировать его для типов, которые должны иметь специальные имена:

template<>
class type_name<std::string> {
public:
    static std::string get() { return "string"; }
};

template<>
class type_name<const char *> {
public:
    static std::string get() { return "string"; }
};

template<int N>
class type_name<const char[N]> {
public:
    static std::string get() { return "string"; }
};

Ваш код будет выглядеть так:

template <typename T> bool SetValue(const std::string &sectionName, 
                                    const std::string &valueName, const T &value)
  {
      myXMl->AddAttribute(TYPE_DEF, type_name<T>::get());
      return true;
  }
4 голосов
/ 17 января 2012

Вы можете обернуть ваш тип в функции подкладки. Эти функции на самом деле не должны быть определены, так как они никогда не будут выполняться; вам нужны только объявления, чтобы использовать разрешение перегрузки, чтобы выбрать правильную функцию для вас, чтобы вы могли получить тип ее результата с помощью выражения typeid ().

Помните, что шаблонные функции выбираются только для идеального соответствия, тогда как перегрузка не шаблонных функций допускает неявные преобразования.

Пример:

#include <string>
#include <iostream>
#include <typeinfo>

struct string{};

template <typename T> T shim(T);
// Not needed, literals will be matched by (const char*) below
// template <size_t S> string shim(const char (&)[S]);
string shim(const char*);
string shim(const std::string&);

int main()
{
  std::cout << typeid(shim(1.0)).name() << "\n"
            << typeid(shim(true)).name() << "\n"
            << typeid(shim(0)).name() << "\n"
            << typeid(shim((void *)NULL)).name() << "\n"
            << typeid(shim("hello there")).name() << "\n"
            << typeid(shim((const char*)"hello there")).name() << "\n"
            << typeid(shim(std::string("hello there"))).name() << std::endl;
}
...