Использовать тип параметра функции в предке
От: szag  
Дата: 29.12.15 09:37
Оценка:
Есть вот такой код:
#include <boost/function_types/function_type.hpp>
#include <boost/function_types/parameter_types.hpp>
#include <boost/function_types/function_arity.hpp>
#include <boost/typeof/std/utility.hpp>
#include <vector>

template<class T>
class foo
{
public:
    typedef typename BOOST_TYPEOF(&T::f) f_type; // error C2039: 'f': is not a member of 'bar'
    typedef typename boost::function_types::parameter_types<f_type> parameter_types;
    typedef typename boost::mpl::at_c< typename parameter_types, 1>::type vec_type;

    std::vector<typename vec_type> vec;
};

class bar : public foo<bar>
{
public:
    void f (int i){}
};

int main()
{
    bar b;
    return 0;
}

и понятно почему ошибка — тип еще готов. Есть ли возможность победить?
Re: Использовать тип параметра функции в предке
От: Warturtle  
Дата: 29.12.15 10:34
Оценка:
Здравствуйте, szag, Вы писали:
Во-первых, кажется, что typename в некоторых местах лишний, ну и "если гора не идет к Магомету, то Магомет идет к горе":
S>Есть вот такой код:
#include <boost/function_types/function_type.hpp>
#include <boost/function_types/parameter_types.hpp>
#include <boost/function_types/function_arity.hpp>
#include <boost/typeof/std/utility.hpp>
#include <vector>

template<class T>
struct foo : public T
{
    typedef typename BOOST_TYPEOF(&T::f) f_type; // error C2039: 'f': is not a member of 'bar'
    typedef typename boost::function_types::parameter_types<f_type> parameter_types;
    typedef typename boost::mpl::at_c< parameter_types, 1>::type vec_type;

    std::vector<vec_type> vec;
};

struct bar
{
    void f (int i){}
};

int main()
{
    foo<bar> b;
    return 0;
}
Re[2]: Использовать тип параметра функции в предке
От: szag  
Дата: 29.12.15 11:14
Оценка:
Здравствуйте, Warturtle, Вы писали:

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

W>Во-первых, кажется, что typename в некоторых местах лишний, ну и "если гора не идет к Магомету, то Магомет идет к горе":
это понятно, но так не подходит. Если бы работал вариант, который показал я, то он бы просто идеально вписался в проект, добавивив неоходимый функционал без каких-либо изменений в остальном проекте.
Re: Использовать тип параметра функции в предке
От: VTT http://vtt.to
Дата: 29.12.15 11:25
Оценка:
Может CRTP поможет?

template<typename tp_Derived> class
bar_base;

template<class T>
class foo
{
public:
  typedef typename BOOST_TYPEOF(&bar_base<T>::f) f_type;
  typedef typename boost::function_types::parameter_types<f_type> parameter_types;
  typedef typename boost::mpl::at_c< typename parameter_types, 1>::type vec_type;

  std::vector<typename vec_type> vec;
};

template<typename tp_Derived> class
bar_base
{
public: void f (int i){} // возможно вызывает настоящий метод в bar
};

class bar : public bar_base<bar>, public foo<bar>
{
};
Говорить дальше не было нужды. Как и все космонавты, капитан Нортон не испытывал особого доверия к явлениям, внешне слишком заманчивым.
Re[2]: Использовать тип параметра функции в предке
От: szag  
Дата: 29.12.15 11:43
Оценка:
Здравствуйте, VTT, Вы писали:

VTT>Может CRTP поможет?


идеальный вариант — это не трогать клалас бар вообще, а вот с фуу можно делать все что угодно. Структура многих проектов такая, что от фуу наследуется вного разных бар, поэтому менять в куче мест сами бары не хотелось бы.
Re[3]: Использовать тип параметра функции в предке
От: Warturtle  
Дата: 29.12.15 12:09
Оценка:
Здравствуйте, szag, Вы писали:

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


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

W>>Во-первых, кажется, что typename в некоторых местах лишний, ну и "если гора не идет к Магомету, то Магомет идет к горе":
S>это понятно, но так не подходит. Если бы работал вариант, который показал я, то он бы просто идеально вписался в проект, добавивив неоходимый функционал без каких-либо изменений в остальном проекте.
Значит надо уточнить почему не годится. Так не вполне ясно, чего ты хочешь. Зачем там обязательно наследование от foo<bar>? Например без него все и сейчас функционирует:
#include <boost/function_types/function_type.hpp>
#include <boost/function_types/parameter_types.hpp>
#include <boost/function_types/function_arity.hpp>
#include <boost/typeof/std/utility.hpp>
#include <vector>
#include <stdio.h>
#include <typeinfo>

template<class T>
class foo
{
public:
    typedef typename BOOST_TYPEOF(&T::f) f_type; // error C2039: 'f': is not a member of 'bar'
    typedef typename boost::function_types::parameter_types<f_type> parameter_types;
    typedef typename boost::mpl::at_c< parameter_types, 1>::type vec_type;

    std::vector<vec_type> vec;
};

class bar 
{
    typedef foo<bar> FooT;
public:
    void f (int i)
    {
        printf("f(%d), vec_type='%s'\n", i, typeid(FooT::vec_type).name());
    }
};

int main()
{
    bar b;
    b.f(123);
    return 0;
}
Re[4]: Использовать тип параметра функции в предке
От: szag  
Дата: 29.12.15 12:22
Оценка:
Здравствуйте, Warturtle, Вы писали:


W>Значит надо уточнить почему не годится. Так не вполне ясно, чего ты хочешь. Зачем там обязательно наследование от foo<bar>? Например без него все и сейчас функционирует:


template<class T>
class foo
{
public:

    typedef typename BOOST_TYPEOF(&T::f) f_type; // сейчас этот тип захардкожен, поэтому все работает, но хочется гибкости
    typedef typename boost::function_types::parameter_types<f_type> parameter_types;
    typedef typename boost::mpl::at_c< parameter_types, 1>::type vec_type;

    void dispatch() // вызывает сам класс foo когда ему это надо
    {
        auto v = vec[0]; // псевдокод получения значения из вектора
        static_cast<T*>(this)->f(v);
    }

    void push(const vec_type& v)
    {
        vec.emplace_back(v);
    }

    std::vector<vec_type> vec;
};

class bar : public foo<bar> // таких классов по коду очень много, не хотелось бы их менять
{
public:
    void f (int i){} // обработка значений
};
Отредактировано 29.12.2015 12:22 szag . Предыдущая версия .
Re[3]: Использовать тип параметра функции в предке
От: Кодт Россия  
Дата: 29.12.15 12:45
Оценка: 3 (1)
Здравствуйте, szag, Вы писали:

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


Судя по коду, требуется параметризовать foo типом первого (и единственного) аргумента bar::f.
Проще всего, в таком случае, передавать тип явно:
template<class CrtpFinal, class Arg>
class foo {
  std::vector<Arg> vec_;
  ...
};

class bar : public foo<bar, int> {
  void f(int);
};


Либо избавляться от наследования.
Ведь у неполных типов две беды: рекурсивное использование имён и рекурсивная зависимость лэяутов.
template<class Y> class x {
  dependent_on<Y> v;
  using z = Y::t;
};

class y : x<y> {
  using t = derivative_of<z>;
};

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

Поэтому делаем так:
#include <memory>
#include <vector>
using namespace std;

template<class Fun> struct first_arg_getter;
template<class R, class A, class... Aaa> struct first_arg_getter<R(*)(A,Aaa...)> {
    using type = A;
};
template<class C, class R, class A, class... Aaa> struct first_arg_getter<R(C::*)(A,Aaa...)> {
    using type = A;
};
#define FIRST_ARG_TYPE(fun) typename first_arg_getter<decltype(fun)>::type

template<class BAR> struct argvecs {
    using fx = FIRST_ARG_TYPE(&BAR::f);
    using gx = FIRST_ARG_TYPE(&BAR::g);

    std::vector<fx> fxs_;
    std::vector<gx> gxs_;
};

template<class BAR> struct foo {
    using aaa = argvecs<BAR>;
    std::unique_ptr<aaa> aaa_; // экстерриториальность спасает!
    
    foo() : aaa_(new aaa()) {}
};

struct bar : foo<bar> {
    static void f(int,char);
    void g(long,short);
};

int main() {
    bar b;
}
Перекуём баги на фичи!
Re[4]: Использовать тип параметра функции в предке
От: szag  
Дата: 29.12.15 13:49
Оценка:
Здравствуйте, Кодт, Вы писали:

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


К>
К>#include <memory>
К>#include <vector>
К>using namespace std;

К>template<class Fun> struct first_arg_getter;
К>template<class R, class A, class... Aaa> struct first_arg_getter<R(*)(A,Aaa...)> {
К>    using type = A;
К>};
К>template<class C, class R, class A, class... Aaa> struct first_arg_getter<R(C::*)(A,Aaa...)> {
К>    using type = A;
К>};
К>#define FIRST_ARG_TYPE(fun) typename first_arg_getter<decltype(fun)>::type

К>template<class BAR> struct argvecs {
К>    using fx = FIRST_ARG_TYPE(&BAR::f);
К>    using gx = FIRST_ARG_TYPE(&BAR::g);

К>    std::vector<fx> fxs_;
К>    std::vector<gx> gxs_;
К>};

К>template<class BAR> struct foo {
К>    using aaa = argvecs<BAR>;
К>    std::unique_ptr<aaa> aaa_; // экстерриториальность спасает!
    
К>    foo() : aaa_(new aaa()) {}
К>};

К>struct bar : foo<bar> {
К>    static void f(int,char);
К>    void g(long,short);
К>};

К>int main() {
К>    bar b;
К>}
К>

да, такой вариант подойдет. Спасибо!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.