Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> boost::bind и шаблонные методы класса, Ошибка: invalid use of void expression 
V
    Опции темы
bsa
Дата 20.10.2009, 14:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



Код иллюстрирующий проблему:
Код
#include <boost/bind.hpp>
#include <cstdlib>
struct A {
    void m1() {
        m2( boost::bind(&A::m3, this) );
    }

    template<class H>
    void m2(H h) {
        boost::bind(&A::m4<H>, this, h)();       //!!!
        //boost::bind(&A::m4<H>, this, boost::cref(h))();
    }

    void m3(){}

    template<class H>
    void m4(H h) {
        if (rand())
            m1();
        else
            h();
    }
};
Вывод компилятора:
Цитата(gcc 4.4.1)
In file included from aaa.cpp:1:
/usr/include/boost/bind.hpp: In member function ‘void boost::_bi::list2<A1, A2>::operator()(boost::_bi::type<void>, F&, A&, int) [with F = boost::_mfi::mf1<void, A, boost::_bi::bind_t<void, boost::_mfi::mf0<void, A>, boost::_bi::list1<boost::_bi::value<A*> > > >, A = boost::_bi::list0, A1 = boost::_bi::value<A*>, A2 = boost::_bi::bind_t<void, boost::_mfi::mf0<void, A>, boost::_bi::list1<boost::_bi::value<A*> > >]’:
/usr/include/boost/bind/bind_template.hpp:20:   instantiated from ‘typename boost::_bi::result_traits<R, F>::type boost::_bi::bind_t<R, F, L>::operator()() [with R = void, F = boost::_mfi::mf1<void, A, boost::_bi::bind_t<void, boost::_mfi::mf0<void, A>, boost::_bi::list1<boost::_bi::value<A*> > > >, L = boost::_bi::list2<boost::_bi::value<A*>, boost::_bi::bind_t<void, boost::_mfi::mf0<void, A>, boost::_bi::list1<boost::_bi::value<A*> > > >]’
aaa.cpp:11:   instantiated from ‘void A::m2(H) [with H = boost::_bi::bind_t<void, boost::_mfi::mf0<void, A>, boost::_bi::list1<boost::_bi::value<A*> > >]’
aaa.cpp:6:   instantiated from here
/usr/include/boost/bind.hpp:292: error: invalid use of void expression
Если заменить подсвеченную строчку на следующую за ней (раскомментировав, естественно), то программа скомпилируется. Но, подозреваю, что корректно работать не будет. Я пробовал в m2 и m4 использовать передачу по ссылке, но это не помогло.
Как мне следует грамотно обойти эту проблему?
PM   Вверх
bsa
Дата 20.10.2009, 16:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



Пока что решил это изменив m2 и m4:
Код
    void m2(boost::function<void()> f) {
        boost::bind(&A::m4, this, f)();
    }
    void m4(boost::function<void()> f) {
        if (rand())
            m1();
        else
            f();
    }
Но мне бы хотелось обойтись без этого.

Это сообщение отредактировал(а) bsa - 20.10.2009, 16:07
PM   Вверх
GoldFinch
Дата 20.10.2009, 19:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Завсегдатай
Сообщений: 2141
Регистрация: 30.11.2008

Репутация: 15
Всего: 26



потому что перегрузка функций. 
юзай static_cast<...>(&A::m4<H>)
PM MAIL ICQ   Вверх
bsa
Дата 21.10.2009, 11:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



GoldFinch, не помогло. Сделал даже через отдельную переменную-указатель на метод - та же ошибка.
Компилятор GCC-4.4.1

Добавлено @ 11:42
Провел еще изыскания...
Так копилируется:
Код
#include <boost/bind.hpp>
#include <boost/function.hpp>

struct A {
    void m1() {
        m2( boost::bind(&A::m3, this) );
    }

    typedef boost::function<void()> F;
    void m2(F h) {
        boost::bind(&A::m4<F>, this, h)();
    }

    void m3(){}

    template<class H>
    void m4(H h) {}
};
Так не копилируется:
Код
#include <boost/bind.hpp>
#include <boost/function.hpp>

struct A {
    void m1() {
        m2( boost::bind(&A::m3, this) );
    }

    template <class F>
    void m2(F h) {
        boost::bind(&A::m4, this, h)();
    }

    void m3(){}

    typedef boost::function<void()> H;
    void m4(H h) {}
};
А так опять копилируется:
Код
#include <boost/bind.hpp>
#include <boost/function.hpp>

struct A {
    void m1() {
        m2( boost::bind(&A::m3, this) );
    }

    typedef boost::function<void()> H;
    template <class F>
    void m2(F h) {
        boost::bind(&A::m4, this, H(h))();
    }

    void m3(){}

    void m4(H h) {}
};
И так тоже:
Код
#include <boost/bind.hpp>
#include <boost/function.hpp>

struct A {
    void m1() {
        m2( boost::bind(&A::m3, this) );
    }

    typedef boost::function<void()> F;
    template <class H>
    void m2(H h) {
        boost::bind(&A::m4<F>, this, F(h))();
    }

    void m3(){}

    template <class H>
    void m4(H h) {}
};
Отсюда напрашивается вывод: не работает только в случае, когда в качестве параметра bind передается объект типа параметра шаблона... С чем это может быть связано?

Это сообщение отредактировал(а) bsa - 21.10.2009, 11:51
PM   Вверх
UnrealMan
Дата 21.10.2009, 15:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 722
Регистрация: 30.3.2006

Репутация: 27
Всего: 32



Вложенный bind не рассматривается как обычный функтор, вместо этого у тебя в первом примере получается композиция функций, т.е. в A::m4 передаётся результат, возвращаемый функцией A::m3. Чтобы предотвратить образование композиции, тебе надо использовать boost::protect.

http://www.boost.org/doc/libs/1_40_0/libs/...ml#nested_binds

И ещё желательно не забывать про использование template для зависимых имён.

Цитата(14.2 paragraph 4)
When the name of a member template specialization appears after . or -> in a postfix-expression, or after
nested-name-specifier in a qualified-id, and the postfix-expression or qualified-id explicitly depends on a
template-parameter (14.6.2), the member template name must be prefixed by the keyword template.
Otherwise the name is assumed to name a non-template.

Код
#include <boost/bind.hpp>
#include <boost/bind/protect.hpp>
#include <cstdlib>
struct A {
    void m1() {
        m2( boost::protect(boost::bind(&A::m3, this)) );
    }
    template<class H>
    void m2(H h) {
        boost::bind(&A::template m4<H>, this, h)();
    }
    void m3(){}
    template<class H>
    void m4(H h) {
        if (rand())
            m1();
        else
            h();
    }
};


Это сообщение отредактировал(а) UnrealMan - 21.10.2009, 15:18
PM MAIL   Вверх
bsa
Дата 21.10.2009, 16:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



boost::protect() помог.
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0882 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.