Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Есть ли такой оператор:


Автор: HappyLife 15.4.2009, 09:55
Доброго времени суток уважаемые форумчане.
Есть ли такой оператор, который позволил бы в функцию передавать лишь конкретный тип, без неявных преобразований.
Например, есть функция:

void f(bool Is)
{
...
}


задача заключается в том, чтобы функцию можно было вызвать одним единственным способом, то есть так:
f(true) или соответственно f(false), безо всякой возможности вызывать её как-то так:
f(10); f(20); f(short(10)); f('a').



Автор: azesmcar 15.4.2009, 10:18
HappyLife

например можно вот так поизвращатся smile 
Код

template <class T>
class wrapper
{
public:
    wrapper(const T& arg): arg_( arg ) {}

    operator T() const {
        return arg_;
    }
private:
    template <class U> wrapper(const U&);
    T arg_;
};

typedef wrapper<bool> wbool;

void foo(wbool is)
{
}

int main()
{
    foo( 5 ); //cannot access private member
    foo( true ); //OK
}


Автор: mes 15.4.2009, 10:19
a зачем такое понадобилось ? если не секрет.  smile 

Автор: azesmcar 15.4.2009, 10:20
Цитата

a зачем такое понадобилось ? если не секрет.  smile  

 smile да да..мне тоже интересно.
В С++ нет такой строгости типов как в Джава. Ничего тут не поделаешь. smile

Добавлено через 2 минуты и 54 секунды
Может задача немного другая на самом деле..а это пример просто?
HappyLife посмотрите explicit конструкторы.

Автор: Ivanovich 15.4.2009, 10:38
нужен шаблон функции и полная специализация шаблона функции
Код

#include <iostream>

using namespace std;

template<typename T> void F(T v)
{
    cout << "template" << endl;
}

template<> void F<bool>(bool v)
{
    cout << "bool " << endl;
}

int main(int argc, char *argv[])
{
    F(true);
    F(30);
    F('w');
}



вывод программы

bool
template
template

убирая определение шаблона, оставив только 
Код

template<typename T> void F(T v); 
 получаются требуемые ошибки компиляции
undefined reference to `void F<int>(int)'
undefined reference to `void F<char>(char)'




Автор: azesmcar 15.4.2009, 10:50
Ivanovich

Тут больше подходит термин - перегрузка.

Автор: mes 15.4.2009, 10:55
Цитата(azesmcar @  15.4.2009,  09:50 Найти цитируемый пост)
Тут больше подходит термин - перегрузка.


Цитата(Ivanovich @  15.4.2009,  09:38 Найти цитируемый пост)
template<typename T> void F(T v);
template<> void F<bool>(bool v)
{
    cout << "bool " << endl;
}

Код

template<typename T> void F(T v);
void F(bool v)
{
    cout << "bool " << endl;
}

Автор: azesmcar 15.4.2009, 11:00
mes
тьфу smile не термин..
тут больше подойдет перегрузка smile
Код

template<typename T> void F(T v)
{
    cout << "template" << endl;
}
void F(bool v)
{
    cout << "bool " << endl;
}


эффект тот же, но пишется как обычная функция.

Автор: Ivanovich 15.4.2009, 11:00
Цитата(azesmcar @ 15.4.2009,  10:50)

Тут больше подходит термин - перегрузка.

перегрузка шаблона функции != специализация шаблона функции

Автор: azesmcar 15.4.2009, 11:07
Ivanovich
Знаю, мой следующий пост посмотри.

Цитата

эффект тот же

Автор: Ivanovich 15.4.2009, 11:13
только надо помнить, что специализации шаблонов функций не перегружают функции и обычная функция void F(bool v) будет вызываться вместо специализации шаблона template<> void F<bool>(bool v)

Автор: azesmcar 15.4.2009, 11:15
Ivanovich
ну потому я и предложил только перегружать. Просто выглядет проще и результат в данном случае будет тот же.

Автор: Alek86 15.4.2009, 11:22
Цитата(mes @  15.4.2009,  10:19 Найти цитируемый пост)
a зачем такое понадобилось ? если не секрет.

немного не в тему, но иногда это очень нужно
у примеру есть функция, что принимает 2 параметра

Код
template <typename T>
void func( std::auto_ptr<int> p, const T& a ) { /*...*/ }


а вызов у нее такой:

Код
int main () {
 MyClass2 m;
 func<MyClass1>(new int, m)
}


при том, что есть неявное преобразование из MyClass2 в MyClass1.
Но если это преобразование выкинет исключение, то велика вероятность утечки памяти.
Потому чтобы еще при проектировании функции func исключить такой шанс, сабж и нужен

если функция шаблонная, то в C++ нормальной возможности избавиться от такого варианта нет, потому в бусте делают примерно так
Код
template <typename T>
void func( std::auto_ptr<int> p, T& a ) { /*...*/ }


некрасиво, но лучше, чем оставлять дырки в либе

Автор: azesmcar 15.4.2009, 11:32
Alek86

Сатер описывает подобную ситуацию с std::auto_ptr и по моему лучшее решение этого вопроса не вызывать функцию принимающую std::auto_ptr подобным образом
Код

func<MyClass1>(new int, m)

а написать
Код

std::auto_ptr<int> ptr( new int );
func<MyClass1>(ptr, m);


Добавлено @ 11:34
правда область видимости тут будет побольше для std::auto_ptr, но если это актуально
Код

{
   std::auto_ptr<int> ptr( new int );
   func<MyClass1>(ptr, m);
}

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

Автор: Alek86 15.4.2009, 11:35
azesmcar, ты пишешь либу, в которой есть эта функция

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

Автор: azesmcar 15.4.2009, 11:39
Цитата

тогда уж зачем эта инкапсуляция, айда делать все методы открытыми, а если юзер неуследит и чето не так вызовет, то сам дурак smile 

Ну по моему это немного другой вопрос нежели инкапсуляция. Пользователь должен писать в соответствии со стандартом С++, уберечь его от всех возможных ошибок все равно нельзя. Это не проблема того кто пишел либу, а проблема пользователя который не знает что С++ не гарантирует очередность вычисления аргументов функции. smile

Добавлено через 18 секунд
хотя если можно его уберечь - конечно желательно.

Автор: HappyLife 15.4.2009, 11:51
Цитата(mes @  15.4.2009,  10:19 Найти цитируемый пост)
a зачем такое понадобилось ? если не секрет.  smile  

Тут нет никакого секрета.
Я произвожу рефакторинг кода.
Когда-то, некая функция имела следующий вид

void f(string str, int t = 0);

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

void f(string str,bool Needed, int t = 0);

Соответственно нужно провести анализ всего немалого кода, чтобы ввести новшество. Но дабы избежать человеческого фактора, из-за которого можно что-то не доглядеть, было прекрасно, чтобы компилятор в таком месте ругнулся.

f("строка",10);

Автор: azesmcar 15.4.2009, 11:54
HappyLife
ну тогда тут два решения вашей проблемы
wrapper который я написал и написанный Ivanovich -ом вариант.

Добавлено через 33 секунды
я так понимаю это временно нужно, пока весь код не исправите?

Автор: mes 15.4.2009, 11:54
Цитата(HappyLife @  15.4.2009,  10:51 Найти цитируемый пост)
К большому бы счастью, было бы прекрасно, если бы в таком месте компилятор ругнулся.

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

Автор: Ivanovich 15.4.2009, 12:19
В старом коде могут быть вызовы типа f("строка", true);  или f("строка", i > 4); с неявным преобразованием bool в int, которые сойдут за новый код.
Такие вопросы решаются переименованием функции - если стали другие аргументы, значит должна быть другая функция.

Автор: Alek86 15.4.2009, 12:27
Цитата(mes @  15.4.2009,  11:54 Найти цитируемый пост)
А еще один вариант, просто  переименовать функцию и всплывут все ее вызовы.

а если есть чуть менее подходящая перегруженная?

Автор: HappyLife 15.4.2009, 15:15
Alek86, очень грамотный вопрос, касающейся всецело тронутой темы рефакторинга.

Автор: Alek86 15.4.2009, 16:54
думаю, проще будет поглядеть на вызовы всех функций с таким названием
к примеру, тупым поиском

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

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)