Перегрузка "operator,"
От: AcidTheProgrammer Россия https://hts.tv/
Дата: 02.10.09 11:03
Оценка:
Знаю что много подводных камней но все же...
Возможно ли на С++ сделать синтаксис типа такого:

method(param1, ..., paramN);


где method это функтор, param1 — paramN неограниченное количество параметров разного типа.
интересует правильная перегрузка operator= и operator, для данного случая.
Re: Перегрузка "operator,"
От: BogusCoder Швеция  
Дата: 02.10.09 11:15
Оценка:
Здравствуйте, AcidTheProgrammer, Вы писали:

ATP>Знаю что много подводных камней но все же...

ATP>Возможно ли на С++ сделать синтаксис типа такого:

ATP>
ATP>method(param1, ..., paramN);
ATP>


ATP>где method это функтор, param1 — paramN неограниченное количество параметров разного типа.

ATP>интересует правильная перегрузка operator= и operator, для данного случая.

Елси типы параметров разные, то следовательно вам пришлось бы перегружать этот оператор в каждом из них. Более того между всеми типами пришлось настраивать те или иные жесткие связи что усложнило бы масштабируемость. Попробуйте пересмотреть дизайн, или воспользуйтесь компилятором который поддерживает variadic templates
Re: Перегрузка "operator,"
От: DKotin  
Дата: 02.10.09 11:27
Оценка:
Здравствуйте, AcidTheProgrammer, Вы писали:

ATP>Знаю что много подводных камней но все же...

ATP>Возможно ли на С++ сделать синтаксис типа такого:

ATP>
ATP>method(param1, ..., paramN);
ATP>


ATP>где method это функтор, param1 — paramN неограниченное количество параметров разного типа.

ATP>интересует правильная перегрузка operator= и operator, для данного случая.


Нет, в таком виде не возможно. Но возможно в виде method((param1, ..., paramN));
Обратите внимание на двойные скобки.
Дело в том, что operator, перегрузить можно. Но при вызове функции работает не operator, а разделение параметров через запятую.
Re[2]: Перегрузка "operator,"
От: AcidTheProgrammer Россия https://hts.tv/
Дата: 02.10.09 11:55
Оценка:
Здравствуйте, DKotin, Вы писали:

DK>Нет, в таком виде не возможно. Но возможно в виде method((param1, ..., paramN));

DK>Обратите внимание на двойные скобки.
DK>Дело в том, что operator, перегрузить можно. Но при вызове функции работает не operator, а разделение параметров через запятую.

Да, я в принципе уже сам догадался до двойных скобок. Но проблемы все-равно остались: выражение в скобках у меня интерпретируется как один параметр, то есть срабатывает встроенный оператор ,, выходом которого является последнее выражение. Как с этим можно бароться?
Re[3]: Перегрузка "operator,"
От: Sergey Chadov Россия  
Дата: 02.10.09 12:23
Оценка:
Здравствуйте, AcidTheProgrammer, Вы писали:


ATP>Да, я в принципе уже сам догадался до двойных скобок. Но проблемы все-равно остались: выражение в скобках у меня интерпретируется как один параметр, то есть срабатывает встроенный оператор ,, выходом которого является последнее выражение. Как с этим можно бароться?


Очевидно, что типом, возвращаемым оператором , должен быть список параметров
Re[3]: Перегрузка "operator,"
От: DKotin  
Дата: 02.10.09 12:26
Оценка:
Здравствуйте, AcidTheProgrammer, Вы писали:

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


DK>>Нет, в таком виде не возможно. Но возможно в виде method((param1, ..., paramN));

DK>>Обратите внимание на двойные скобки.
DK>>Дело в том, что operator, перегрузить можно. Но при вызове функции работает не operator, а разделение параметров через запятую.

ATP>Да, я в принципе уже сам догадался до двойных скобок. Но проблемы все-равно остались: выражение в скобках у меня интерпретируется как один параметр, то есть срабатывает встроенный оператор ,, выходом которого является последнее выражение. Как с этим можно бароться?


Так тут и нужна перегрузка operator, для твоего класса.

Пусть у тебя method принимает параметр типа List
method(const List& list)

тогда в list нужены конструкторы, которые принимают типы параметров param1, param2
List::List(const Param1& param1)
List::List(const Param2& param2)
само собой, что в List должены хранится все param.

и в List нужно перегрузить operator, . При этом ндо перегрузить operator, для типа List и для всех типов Param.
const List operator,(const List& list);
const List operator,(const Param1& param1);
const List operator,(const param2& param2);


p.s. В С++ перегрузка operator, выглядит очень плохо. Попробуте пересмотреть дизайн или воспользоваться другим оператором (например operator+ тогда будет так method(param1 + param2 + .... + paramN)
Re[4]: Перегрузка "operator,"
От: AcidTheProgrammer Россия https://hts.tv/
Дата: 02.10.09 13:04
Оценка:
Здравствуйте, DKotin, Вы писали:

DK>Так тут и нужна перегрузка operator, для твоего класса.


DK>Пусть у тебя method принимает параметр типа List

DK>method(const List& list)

DK>тогда в list нужены конструкторы, которые принимают типы параметров param1, param2

DK>List::List(const Param1& param1)
DK>List::List(const Param2& param2)
DK>само собой, что в List должены хранится все param.

DK>и в List нужно перегрузить operator, . При этом ндо перегрузить operator, для типа List и для всех типов Param.

DK>const List operator,(const List& list);
DK>const List operator,(const Param1& param1);
DK>const List operator,(const param2& param2);


DK>p.s. В С++ перегрузка operator, выглядит очень плохо. Попробуте пересмотреть дизайн или воспользоваться другим оператором (например operator+ тогда будет так method(param1 + param2 + .... + paramN)


В том то и дело, что с Param у меня все работает, не работает например такой код:
method((1, 4))

— передается один параметр 4, о чем я писал выше.
Re[5]: Перегрузка "operator,"
От: DKotin  
Дата: 02.10.09 13:23
Оценка:
Здравствуйте, AcidTheProgrammer, Вы писали:

ATP>В том то и дело, что с Param у меня все работает, не работает например такой код:

ATP>
ATP>method((1, 4))
ATP>

ATP> — передается один параметр 4, о чем я писал выше.

Забыл.
Нужен еще const List operator,(const Param1& lhs, const Param1& rhs); При этом подобные оперетры нужны для всех типов Param, плюс нужны операторы типа const List operator,(const Param1& lhs, const Param2& rhs); Лучше подобные вещи реализовывать через шаблоны.

И еще раз method должен принимать List, а не перам. Ввиду того, что у тебя код скомпилировался, то у тебя method принимает Param, а не List
Re[6]: Перегрузка "operator,"
От: AcidTheProgrammer Россия https://hts.tv/
Дата: 02.10.09 13:37
Оценка:
Здравствуйте, DKotin, Вы писали:

DK>Забыл.

DK>Нужен еще const List operator,(const Param1& lhs, const Param1& rhs); При этом подобные оперетры нужны для всех типов Param, плюс нужны операторы типа const List operator,(const Param1& lhs, const Param2& rhs); Лучше подобные вещи реализовывать через шаблоны.

DK>И еще раз method должен принимать List, а не перам. Ввиду того, что у тебя код скомпилировался, то у тебя method принимает Param, а не List


Есть у меня такой оператор — всеравно выражение method((1, 4)) воспринимается как method(Param(4)), а мне бы хотелось method((Param(1), Param(4))). Проблемма, если в скобках стоят только стандартные типы. А нельзя ли минимальный примерчик... Предположим что класс Param есть и он может хранить любой тип
Re[7]: Перегрузка "operator,"
От: DKotin  
Дата: 02.10.09 14:47
Оценка:
Здравствуйте, AcidTheProgrammer, Вы писали:
#include <vector>
#include <iostream>


class Param
{
public:
    Param(int value)
    {
        m_value = value;
    }

    const int Value() const
    {
        return m_value;
    }

private:
    int m_value;
};


class List
{
public:
    List(const Param& param)
    {
        m_list.push_back(param);
    }

public:
    const List add(const Param& param)
    {
        m_list.push_back(param);
        return *this;
    }

    const std::vector<Param> get() const
    {
        return m_list;
    }

private:
    std::vector<Param> m_list;
};


const List operator,(const Param& rhs, const Param& lhs)
{
    List list(rhs);
    list.add(lhs);
    return list;
}


const List operator,(List& list, const Param& param)
{
    return list.add(param);
}

const List operator,(const Param& param, List& list)
{
    return list.add(param);
}

const List operator,(const List& rhs, const List& lhs)
{
    std::vector<Param> v = lhs.get();

    List list = rhs;

    for (std::vector<Param>::const_iterator i = v.begin(); i != v.end(); ++i)
    {
        list.add(*i);
    }

    return list;
}


void method(const List& list)
{
    std::vector<Param> v = list.get();

    for (std::vector<Param>::const_iterator i = v.begin(); i != v.end(); ++i)
    {
        std::cout << i->Value();
    }
}



int main()
{
    method((Param(1), Param(4), Param(5)));

    return 0;
}
Re: Перегрузка "operator,"
От: Кодт Россия  
Дата: 02.10.09 14:53
Оценка: 5 (2) +1
Здравствуйте, AcidTheProgrammer, Вы писали:

ATP>Знаю что много подводных камней но все же...


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

Чтобы заработал именно перегруженный оператор, нужно
— двойные скобки — чтобы компилятор не принял монолитное выражение за список аргументов
— первый аргумент с перегруженной запятой
method((start, x, y, z));

Это ничем не красивее такого варианта
method(start << x << y << z);
method(start % x % y % z);
method(start(x)(y)(z));

А может, вот так сделать?
curried(method)(x)(y)(z);


Но на самом деле, можно поступить проще. Отказаться от амбиций в велосипедостроении и воспользоваться boost
boost::bind(method, x, y, z);
method(boost::tuple(x,y,z));

в зависимости от того, что именно тебе надо.

Там уже с помощью препроцессора нагенерили достаточно перегрузок по числу параметров.
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Перекуём баги на фичи!
Re[2]: Перегрузка "operator,"
От: AcidTheProgrammer Россия https://hts.tv/
Дата: 05.10.09 08:08
Оценка:
Здравствуйте, Кодт, Вы писали:

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

К>Скобки там, %, <<

К>Чтобы заработал именно перегруженный оператор, нужно

К>- двойные скобки — чтобы компилятор не принял монолитное выражение за список аргументов
К>- первый аргумент с перегруженной запятой
К>
К>method((start, x, y, z));
К>

К>Это ничем не красивее такого варианта
К>
К>method(start << x << y << z);
К>method(start % x % y % z);
К>method(start(x)(y)(z));
К>

К>А может, вот так сделать?
К>
К>curried(method)(x)(y)(z);
К>


К>Но на самом деле, можно поступить проще. Отказаться от амбиций в велосипедостроении и воспользоваться boost

К>
К>boost::bind(method, x, y, z);
К>method(boost::tuple(x,y,z));
К>

К>в зависимости от того, что именно тебе надо.

К>Там уже с помощью препроцессора нагенерили достаточно перегрузок по числу параметров.


ОК, исчерпывающий ответ, теперь все ясно.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.