2016-02-10 3 views
0

У меня есть следующие функции:Как вставить тип переменной в качестве функции параметра?

int readAndCheck() { 
    int n; 
    while (n < 2) { 
     try { 
      cout << "Please insert an integer bigger than one: "; 
      string check = ""; 
      cin >> check; 
      n = boost::lexical_cast<int>(check); 
     } catch (boost::bad_lexical_cast&) { 
      cout << "Error!\n"; 
     } 
    } 
    return n; 
} 

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

checktype readAndCheck (string request, checktype) { 
    checktype n; 
    while (n < 2) { 
     try { 
      cout << request; 
      string check = ""; 
      cin >> check; 
      n = boost::lexical_cast<checktype>(check); 
     } catch (boost::bad_lexical_cast&) { 
      cout << "Error!\n"; 
     } 
    } 
    return n; 
} 
  1. Как я могу создать переменную, которая содержит тип как CheckType (это возможно)?

  2. Какой способ создать обобщенную функцию readAndCheck для любого возможного значения checktype?

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

РЕШЕНИЕ:

#include <iostream> 
#include <boost/lexical_cast.hpp> 

template<typename CheckType> 
CheckType readAndCheck(std::string request, CheckType n) 
{ 
    try { 
     std::cout << request; 
     std::string check = ""; 
     std::cin >> check; 
     n = boost::lexical_cast<CheckType>(check); 
    } catch (boost::bad_lexical_cast&) { 
     std::cout << "Error!\n"; 
    } 
    return n; 
} 

int main() 
{ 
    int a = 0; 
    while (a < 2) 
     a = readAndCheck("Please insert a integer bigger than one: ", a); 
    std::cout << a << "\n"; 
    return 0; 
} 
+1

Это помеченный C++, и все же вы, похоже, не знаете, что существуют шаблоны. Что с этим? –

+0

Я начал изучать C++, как неделю назад. Я просто посмотрел, какие шаблоны. Интересно, но не могли бы вы немного разобраться? – Pigna

ответ

2

Один из нескольких столпов C++ это функция называется template s, и один из них (много) основных причин существующего именно облегчить такие ситуации, где в противном случае потребуется очень повторяющийся код.

документация более чем в изобилии, но вкратце, идея объявляется template d класса или функции, с родовыми типами или интеграл (включая указатели) аргументов шаблона как заполнители для реальных типов или значений. template не является типом, пока вы не получите экземпляр этот шаблон со всеми необходимыми аргументами, создавая из него фактический тип/код.

Вы инстанцируете template через декларацию для класса (например, MyTemplate<Arguments> myInstance{ctor_args}), или для функций, декларация или вызов (например, myFunc<OptionalArguments>(func_args); см также ниже). Аргументы, которые вы предоставляете во время создания экземпляра, заменяются (в далеком более сложным способом, чем макросы!) Для заполнителей, указанных ранее, наконец, создавая конкретный класс шаблона (и связанный код) или функцию, которая содержит или действует на указанные типы/интегральные значения.

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

шаблона функции часто не нужно, чтобы явно указать аргументы шаблона, если таковые могут быть однозначно выведены из места вызова (т.е. типом аргумента функции). Если аргументы шаблона не могут быть выведены (, например, нет соответствующего аргумента функции), тогда вы должны предоставить их при вызове в <Brackets>, как и при создании экземпляра класса шаблона.

я не могу проверить код прямо сейчас (и я не знаю, как boost::lexical_cast работы), но ваш простой случай будет что-то так:

// Return a new instance - can't deduce type, must specify at call site 
// Call like: auto checked{ readAndCheck<YourType>(yourRequest) }; 
template<typename T_CheckType> 
T_CheckType readAndCheck(std::string request) 
{ 
    // assumes T_CheckType not initialised with gibberish: 
    T_CheckType n; 

    while (n < 2) { // assumes T_CheckType convertible to int 
     try { 
      std::cout << request; 
      std::string check = ""; 
      std::cin >> check; 
      n = boost::lexical_cast<T_CheckType>(check); 
     } catch (boost::bad_lexical_cast&) { 
      std::cout << "Error!\n"; // may return invalid instance 
     } 
    } 
    return n; 
} 

// XOR 

// Write result to passed output parameter - enables deduction from arg #2 
// Call like: readAndCheck(yourRequest, yourOutputParameter); 
template<typename T_CheckType> 
void readAndCheck(std::string request, T_CheckType &output_checked) 
{ 
    // reinitialise output_checked here if required 

    while (output_checked < 2) { // assumes T_CheckType convertible to int 
     try { 
      std::cout << request; 
      std::string check = ""; 
      std::cin >> check; 
      output_checked = boost::lexical_cast<T_CheckType>(check); 
     } catch (boost::bad_lexical_cast&) { 
      std::cout << "Error!\n"; 
     } 
    } 
} 

В противном случае все, что документация об обучении шаблонов должно помочь you out ;-)

+0

, когда я запускаю его, первое примечание: 'не удалось вывести параметр шаблона 'T_CheckType'':/ – Pigna

+0

В вашем последнем проекте' readAndCheck() ', T_CheckType не может быть выведен, поскольку нет параметра функции из которого вывести его. Таким образом, вы должны либо изменить подпись функции, которая будет выводима (_e.g._ через выходной параметр), либо просто указать нужный тип явно при вызове: 'auto checked {readAndCheck (request)};'. Добавлены некоторые непроверенные иллюстрации к моему сообщению. Я думаю, что это довольно просто, поэтому учебник о шаблонах лучше объяснит это, чем назад и вперед в этой теме, или мои объяснительные навыки ;-) –

Смежные вопросы