Интересная дилемма, перегрузка шаблона
От: johny5 Новая Зеландия
Дата: 08.02.13 16:19
Оценка:
Всем привет.

Есть у меня код, позволяющий запросить параметр с класса по такому синтаксису:
// описание контейнера параметров
struct OneOfParamCont
{
    int param1;
    float param2;
};

// объект, может реализовать любой из классов параметров
struct Object
{
    // запрос параметра у объекта
    // если объект хранит в себе OneOfParamCont, то ф-ция вернёт значение параметра
    // иначе вернёт defaultVal 
    template<typename ParamClass, typename ParamType>
    ParamType  QueryParam( ParamType (ParamClass::*param), const ParamType& defaultVal = ParamType() )
    { ... }
};


Запросы вот такие:
int val = object.QueryParam( &OneOfParamCont::param1 );
float val2 = object.QueryParam( &OneOfParamCont::param2, 1.f );


Всё работает замечательно, но захотелось мне добавить перегрузку, чтобы возвращаемое значение можно было задавать самому, по такому синтаксису:
std::string = object.QueryParam<std::string>( &OneOfParamCont::param1 );

т.е. какой бы ни был реальный тип параметра, он конвертнётся в строку автоматом.

Но тут возник затык с декларацией ф-ции. Описываем перегрузку вот так:
    template<typename ResultType, typename ParamClass, typename ParamType>
    ResultType  QueryParam( ParamType (ParamClass::*param), const ResultType& defaultVal = ResultType() )
    { ... }


и вот такой код уже ломается компилироваться:
float val2 = object.QueryParam( &OneOfParamCont::param2, 1.f );


жалуется на ambiguity, потому что обе ф-ции подходят под определение, для второй декларации ResultType выводится из дефолтного значения

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

Какие будут идеи?
Re: Интересная дилемма, перегрузка шаблона
От: Piko  
Дата: 08.02.13 17:11
Оценка:
Ты хотя бы полный пример показал. У меня и на gcc и на vs компилится: http://ideone.com/bZaHQl

J> template<typename ParamClass, typename ParamType>

J> ParamType QueryParam( ParamType (ParamClass::*param), const ParamType& defaultVal = ParamType() )
J> { ... }

как вариант попробуй поменять местами параметры шаблона у этой функции.

P.S. А что у тебя внутри делает функция с ResultType? static_cast?
Re[2]: Интересная дилемма, перегрузка шаблона
От: johny5 Новая Зеландия
Дата: 09.02.13 06:50
Оценка:
Здравствуйте, Piko, Вы писали:

P>Ты хотя бы полный пример показал. У меня и на gcc и на vs компилится: http://ideone.com/bZaHQl


J>> template<typename ParamClass, typename ParamType>

J>> ParamType QueryParam( ParamType (ParamClass::*param), const ParamType& defaultVal = ParamType() )
J>> { ... }

P>как вариант попробуй поменять местами параметры шаблона у этой функции.


Не совсем понял. Вот так?
template<typename ParamType, typename ParamClass>
ParamType  QueryParam( ParamType (ParamClass::*param), const ParamType& defaultVal = ParamType() )

template<typename ResultType, typename ParamType, typename ParamClass>
ResultType  QueryParam( ParamType (ParamClass::*param), const ResultType& defaultVal = ResultType() )

// остаётся abmiguity по тем же самым причинам
float val2 = object.QueryParam( &OneOfParamCont::param2, 1.f );



P>P.S. А что у тебя внутри делает функция с ResultType? static_cast?

Вызывает конвертер. Впрочем это детали мимо дела — реальный код несколько сложнее, не хочу вдаваться в подробности без насущной необходимости.
Re[3]: Интересная дилемма, перегрузка шаблона
От: Piko  
Дата: 09.02.13 07:58
Оценка: 8 (1)
Здравствуйте, johny5, Вы писали:

P>>Ты хотя бы полный пример показал. У меня и на gcc и на vs компилится: http://ideone.com/bZaHQl


Так у тебя мой пример скомпилировался?

P>>как вариант попробуй поменять местами параметры шаблона у этой функции.

J>Не совсем понял. Вот так?

да

P>>P.S. А что у тебя внутри делает функция с ResultType? static_cast?

J>Вызывает конвертер. Впрочем это детали мимо дела — реальный код несколько сложнее, не хочу вдаваться в подробности без насущной необходимости.

ну ок, просто если static_cast — то вся эта конструкция лишняя..
Re[4]: Интересная дилемма, перегрузка шаблона
От: johny5 Новая Зеландия
Дата: 09.02.13 13:25
Оценка: 1 (1)
Здравствуйте, Piko, Вы писали:

P>Здравствуйте, johny5, Вы писали:


P>>>Ты хотя бы полный пример показал. У меня и на gcc и на vs компилится: http://ideone.com/bZaHQl


P>Так у тебя мой пример скомпилировался?


P>>>как вариант попробуй поменять местами параметры шаблона у этой функции.

J>>Не совсем понял. Вот так?

P>да


Подожди, оно собирается и твоё и даже моё оригинальное...
В общем я разобрался — как обычно бывает, упрощая, я упростил выкинув проблемное место, и т.е. проблему я искал не там. В оригинале QueryParam были размножены (в отсутствии вариадиков) до N параметров, так что в одном QueryParam можно спрашивать параметр от разных классов (лишь бы результирующие типы совпадали).
struct SecondParamCont
{
    float param2;
};

float val = QueryParam( &OneOfParamCont::param2, &SecondParamCont::param2 );


Размножение я поленился делать корректным и выглядело оно так:
    template<typename ParamClass, typename ParamType, typename Param2>
    ParamType  QueryParam( ParamType (ParamClass::*param), Param2 param2, const ParamType& defaultVal = ParamType() ) const
    {
        return defaultVal;
    }
    template<typename ResultType, typename ParamClass, typename ParamType, typename Param2>
    ResultType  QueryParam( ParamType (ParamClass::*param), Param2 param2, const ResultType& defaultVal = ResultType() ) const
    {
        return defaultVal;
    }
...


И неоднозначность возникала именно из-за них, ибо на место typename Param2 подставлялись явно заданные дефолтные аргументы и всё ломалось.
Переписав менее абстрактно, вот так:
 .., typename ParamClass2>
 ... , ParamType (ParamClass2::*param2), ...


всё стало выводиться нормально.
Доберусь до работы (в среду) опробую.

Спасибо за помощь!
Re[5]: Интересная дилемма, перегрузка шаблона
От: jazzer Россия Skype: enerjazzer
Дата: 10.02.13 05:39
Оценка:
Здравствуйте, johny5, Вы писали:

J>Доберусь до работы (в среду) опробую.


О, у вас чтят день субботний?
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[6]: Интересная дилемма, перегрузка шаблона
От: johny5 Новая Зеландия
Дата: 10.02.13 05:42
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Здравствуйте, johny5, Вы писали:


J>>Доберусь до работы (в среду) опробую.


J>О, у вас чтят день субботний?


Да, в этот раз аж 4ре дня выходных...
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.