C ++ преобразовать строку в typename - PullRequest
0 голосов
/ 02 июля 2018

Итак, я нашел множество статей и постов, в которых говорится, что нет способа конвертировать typename в string, но я не нашел ни одного об обратном. У меня есть template функции со специализациями:

template <typename T>
void foo(T sth) {}

template <>
void foo<int>(int sth) {}
...

и я читаю из файла, сконструированного так:

int 20
double 12.492
string word

Есть ли способ вызвать правильную специализацию foo() в зависимости от содержимого файла?

Ответы [ 2 ]

0 голосов
/ 02 июля 2018

Если честно, я не уверен в понимании вашего вопроса. Насколько я понимаю, я считаю, что вам не нужен своего рода диспетчер во время выполнения, чтобы вычислить строку, содержащую имя типа. Просто вы пишете общую функцию шаблона, которая вызывает специальную оболочку шаблона, которая устраняет неоднозначность вызова foo() в соответствии с типом. Требуется, чтобы специализированный foo() получил второй специальный параметр (the_type<T>), который используется для устранения неоднозначности.

Вот полная и действующая демонстрация:

# include <string>
# include <iostream>

using namespace std;

template<class T> struct the_type { using type = T; };

template <typename T>
void foo(const T par)
{
  foo(par, the_type<T>());
}

void foo(int par, the_type<int>)
{
  cout << "int " << par << endl;
}

void foo(double par, the_type<double>)
{
  cout << "double " << par << endl;
}

void foo(const string & par, the_type<string>)
{
  cout << "string " << par << endl;
}

void foo(const char * par, the_type<const char*>)
{
  cout << "char* " << par << endl;
}    

int main()
{
  foo(20);
  foo(12.492);
  foo("word");
  foo(string("word"));
}

чей вывод:

int 20
double 12.492
char* word
string word

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

Вы можете использовать макро-манипуляции, чтобы избежать повторяющихся вещей. Например, если структура foo() одинакова, вы можете инкапсулировать ее в макрос. Примерно так:

# define GENFOO(type_name)                      \
  void foo(type_name par, the_type<type_name>)  \
  {                                             \
    cout << #type_name " " << par << endl;      \
  }

GENFOO(int);
GENFOO(double);
GENFOO(string)

Однако я бы сказал, что каждая специализированная версия foo() не будет такой похожей.

0 голосов
/ 02 июля 2018

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

Вы всегда можете использовать препроцессор или другие приемы, чтобы попытаться уменьшить шаблон, если хотите.

void callFoo(std::string type, std::any arg) {
  if (type == "int")
      foo<int>(std::any_cast<int>(arg));
  else if (type == "double")
      foo<double>(std::any_cast<double>(arg));
  else if (type == "string")
      foo<std::string>(std::any_cast<std::string>(arg));
}

Конечно, это требует, чтобы вы передали правильный тип (без неявных преобразований!). Я не вижу способа избежать этого.

...