Шаблоны функций и приведение типов — что за дискриминация bool?

 

Создаю шаблонную функцию:

template<typename T>
void SetValue( string some_str, T &variable )
{
    variable = (T)some_str;
};

И все с ней хорошо, пока не пытаешься в качестве variable передать bool. На это компилятор ругается:

cannot convert type 'string' to 'bool'
   in template 'bool SetValue(const string,T&)' specified with [T=bool]


Обмануть его с помощью

if ( typename(T) == "bool" )
   variable = StringToBool( some_str );
else
   variable = (T)some_str;

не получается, так как он проверяет все ветки, но не понимает, что переменная bool не попадет в ветку else, и все равно ругается.


Собственно, вопрос: почему не работает приведение string к bool? Это же строка кода.

Приходится делать перегрузку специально для bool:

void SetValue( string some_str, bool &variable )
{
    variable = StringToBool( some_str );
};

а это именно то, от чего хотели уйти с помощью шаблона.

 
Andrey Khatimlianskii:

Создаю шаблонную функцию:

сделай перегрузку для bool.

у тебя вид функции в баге и в коде отличается

в mql нету прямого каста строки в bool, т.е. такой код:

   bool b = (bool)"true";

не компилится

как вариант:

template<typename T>
void SetValue( string some_str, T &variable )
{
    variable = (T)some_str;
}

void SetValue( string some_str, bool &variable )
{
    // all that is not "false" is true
    string lower = some_str;
    if (!StringToLower(lower))
    {
        variable = true;
        return;
    }
    variable = (lower != "false");
}
 
Не проверял.
template<typename T>
void SetValue( string some_str, T &variable )
{
    variable = (T)(double)some_str;
};
 

Можно в самой функции сделать ветвление:

template<typename T>
void SetValue( string some_str, T &variable )
{
   if (typename(T) == "bool")
   {
       string lower = some_str;
       if (!StringToLower(lower))
       {
           variable = true;
           return;
       }
       variable = (lower != "false");
       return;
   }
   
   variable = (T)(double)some_str;
};
 
TheXpert:

сделай перегрузку для bool.

Ну так я и сделал, написал же сразу. Но именно от ненужных перегрузок и хотелось уйти.


TheXpert:

в mql нету прямого каста строки в bool

Именно об этом и речь! Не понятно, почему нельзя его привести.

 
fxsaber:
Не проверял.

Так ломается приведение стрингов, например. Возможно, и еще чего-то.

 
Ihor Herasko:

Можно в самой функции сделать ветвление:

Об этом тоже сразу написал.

Не работает! Компилятор не достаточно умный, чтобы на этапе компиляции разобраться, что бул не попадет не в свою ветку, и все равно ругается.

А вариант с (T)(double) ломает другое приведение.

 

Не понимаю, почему Вас не устраивает перегрузка для bool, но устроило бы это:

if ( typename(T) == "bool" )
   variable = StringToBool( some_str );
else
   variable = (T)some_str;

Перегрузка здесь оптимальный вариант.

 
Koldun Zloy:

Не понимаю, почему Вас не устраивает перегрузка для bool, но устроило бы это:

Перегрузка здесь оптимальный вариант.

В идеале, хотелось бы нормального приведения стринга к булу )

А так, конечно, решение есть, и я его использую.

 
Andrey Khatimlianskii:

Ну так я и сделал, написал же сразу. Но именно от ненужных перегрузок и хотелось уйти.

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

Если ты делаешь ветвление через typename, ты переносишь выбор функции в рантайм.

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

 
TheXpert:

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

Если ты делаешь ветвление через typename, ты переносишь выбор функции в рантайм.

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

Вопрос не в шаблоне, а в приведении стринга к булу.

А компилятор не дает перенести выбор в рантайм, ругается. Но это костыль, он не интересен.