2012-02-08 3 views
4

Как описано in another message of mine, невозможно сравнить 2 указателя с функциями-членами с «<» (менее). По крайней мере, это приводит к неопределенному поведению.Указатели функций и методов в std :: set

Я только что удалось скомпилировать этот код как с помощью Visual C++, а также GCC:

template <class Receiver, class Param = void*, class Return = void> 
class EventReceiver : public IFunction<> { 

protected: 

    std::set< Return(Receiver::*)(Param) > test; 
    std::set< Return(*)(Param) > test2; 
... 

AFAIK, чтобы сделать зЬй :: карту или зЬй :: набор ничего, оно должно быть возможным сравните значения набора с «<». Означает ли это, что вышеупомянутые контейнеры или фактические компиляторы имеют рабочую реализацию сравнения методов указателей на методы таким образом?

+0

Мой ответ был неправильным - указатели на элемент и указатели не совпадают. Мои извинения! – templatetypedef

+0

@templatetypedef FWIW соответствующая формулировка в C++ 11 приведена в § 20.8.5/8. Это неудивительно. Я пригласил некоторых (компиляторов) друзей, чтобы сказать здесь – sehe

+0

@Xeo дала идею [в чате] (http://chat.stackoverflow.com/transcript/message/2582471#2582471) – sehe

ответ

0

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

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

Проверьте это:

#include <set> 

class X {}; 

int main() { 

    typedef void(X::*FuncPtr)(); 
    std::set<FuncPtr> set; 
    std::less<FuncPtr> less; 
    FuncPtr f1; 
    FuncPtr f2; 
    //set.insert(f1); // both of these lines 
    //less(f1,f2);  // produce an error 
}; 

Удаление комментариев в любой из последних 2-х линий дает ошибку:

недопустимые операнды ничтожной (X :: * сопзЬ) Types»() 'и 'недействительным (X :: * Const)()' в двоичный 'оператор <'

Compile it online yourself here.

0

std::set<T> использует std::less<T>, вместо прямого использования оператора. Если T - тип указателя, то std::less<T> гарантированно будет полным, даже если оператор меньше, чем оператор.

Редактировать: В разделе 20.3.3 стандарта C++ 98 говорится «типы указателей», которые (я думаю) включает указатели на функции, но не указатели на элементы.

+1

«специализации для любого типа указателя дают общий порядок, даже если встроенные операторы <, >, <=, > = не делают». - Теперь вопрос в том, является ли тип «указатель на член» также «указательным» типом? Стандарт, кажется, говорит «нет», см. Другой вопрос. – Xeo

+0

Вы правы. Я исправил свой ответ. –

+1

Ну, std :: less тоже не работает! [std :: less (). operator() (function, other-> function))] не компилируется: ошибка C2296: '<': незаконна, левый операнд имеет type 'void (__thiscall Fair :: PtrIcon :: * const) (Fair :: Pointer *)' !!! –

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