Определить тип результата шаблонной функции во время компиляции? - PullRequest
1 голос
/ 07 июля 2010

Я не уверен, что это возможно, но есть ли способ, используя магию программирования шаблонов, определить функцию, которая имеет различные возвращаемые значения в зависимости от того, какой ввод требуется?

Потенциально:

template<typename resultType>
resultType GetResult(const std::string &key); // where the value of key may change resultType

template<typename keyType, typename resultType>
resultType GetResult(keyType key);

Теперь я знаю, что вышеприведенное неверно.Чтобы использовать первый, вы должны знать, что было resultType перед вызовом функции.Тем не менее, я узнал, что многие «невозможные» вещи часто становятся возможными только с помощью другого (или двух) уровня косвенности.Кажется, я просто не могу найти правильный способ сделать это.

Хотя второй вариант щекочет мне мозг.Я чувствую, что должен быть в состоянии определить какой-то другой вспомогательный объект, который отображает строки в типы (или что-то еще), а затем результат компиляции этого времени вызовет GetResult с соответствующим параметром шаблона.

Редактировать:Предположим, что типы, используемые для resultType, не связаны.Нет интерфейса, который можно было бы проверить на «настоящий» тип (возможно, это может быть int и MyClass *).

Редактировать 2: Реальное использование заключается в том, что яполучил сторонний объект, который содержит коллекцию виджетов, гаджетов и т. д. Вы можете запросить их по строковому идентификатору (удобно с префиксом типа), но вам нужно проанализировать строку, чтобы выяснить, что вам нужно вызвать "collectionInstance.getWidget (идентификатор)».Мой план состоял в том, чтобы написать тонкий объект-обертку, который разумно знал бы, как добраться до этих внутренних объектов.

Ответы [ 4 ]

2 голосов
/ 07 июля 2010

Нет. Вы не можете сделать тип возвращаемого значения, определенный во время компиляции, зависящим от значения времени выполнения.

Вы можете вернуть boost :: variable или boost :: any, однако.

2 голосов
/ 07 июля 2010

Вам нужна вспомогательная метафункция, которая отобразит эти типы во втором примере.typename helper<keyType>::type будет вашим возвращаемым типом, а параметр шаблона keyType будет удален.Ваша вспомогательная метафункция должна будет создать type typedef в зависимости от его параметра шаблона.Вы можете найти boost :: mpl :: map полезной утилитой для этой задачи и, возможно, BOOST_STRONG_TYPEDEF для определения различных типов на основе std :: string.

0 голосов
/ 07 июля 2010

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

    template <typename keyType>
    class GetResult
    {
      keyType mkey;

      GetResult(keyType key) : mkey(key) {}

      template <typename resultType>
      operator resultType()
      {
           //do stuff here that returns result type
      }
    }
0 голосов
/ 07 июля 2010

Исходя из ваших правок, вы хотите не то, о чем вы просите.Вам нужно:

1) Способ хранения переменной любого типа среди несвязанных типов X, Y, Z.2) Способ синтаксического анализа вашей строки, чтобы выяснить, какую функцию вызывать для получения вашей переменной.

Первая может быть решена с помощью boost :: option.

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

boost::variant<X,Y,Z> get_result(std::string stuff)
{
    return parser::instance().get_call(stuff).make_call(stuff);
}

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...