LINUX.ORG.RU

что значит «выдрать»? если вы хотите чтобы какой-нибудь

GetSignature<Functor<void, void*, void*>> x;
cout<<GetSignature.show_ret(); 

показывал «void», то не выйдет

anonymous
()
Ответ на: комментарий от anonymous

Смысл вот в чем:

template <class Func> void Foo(Func func)
{
	//if we pass here a int bar(int x);
	// Func will be int(*)(int)
}
Хочется получить тип int(int) если темплейт инстанцирован классом Bar из примера выше

CatsCantFly
() автор топика

template<class Functor> struct GetSignature { Functor func; }

GetSignature<Foo> x;

decltype(x.func()) y; //int y;

не оно?

anonymous
()
Ответ на: комментарий от four_str_sam

Нет, так мы получим только возвращаемый тип, который может быть выведен при вычислении Functor::operator(), то есть int в примере выше. Хочется получить тип функции - int(int) (ну или хотя бы int(Bar*, int) - на самом деле там тип такой.

CatsCantFly
() автор топика
Ответ на: комментарий от CatsCantFly
#include <iostream>
#include <typeinfo>

class Foo
{
public:
        int operator()(int x) {}
};

template<class Functor>
struct GetSignature
{
        using type = decltype( &Functor::operator() );
};

int
main(void)
{
    std::cout << typeid(GetSignature<Foo>::type).name() << std::endl;
    return 0;
}
$ c++filt -t `./a.out`
int (Foo::*)(int)

А что ещё нужно?

xaizek ★★★★★
()

Не гуру TMP, но можно как-то так

struct Foo
{
	int operator()(int x, float y) { return 0; }
};

template<typename FunctorT> class GetSignature
{
    template<typename ResultT, typename... ParamsT>
    static auto stripClass(ResultT (FunctorT::*)(ParamsT...))
    {
        ResultT tmp(ParamsT...);
        return tmp;
    }
public:
    typedef decltype(stripClass(&FunctorT::operator())) type;
};


int main()
{
    GetSignature<Foo>::type foo = "hello";
    return 0;
}

По тексту ошибки тип получился тот что нужно, вроде

g++-4.9 -std=c++14 -o foo foo.cc 
foo.cc: In function ‘int main()’:
foo.cc:21:35: error: cannot convert ‘const char*’ to ‘GetSignature<Foo>::type {aka int (*)(int, float)}’ in initialization
     GetSignature<Foo>::type foo = "hello";

anonymous
()
Ответ на: комментарий от CatsCantFly

Хочется получить тип int(int) если темплейт инстанцирован классом Bar из примера выше

Если я правильно понял ТЗ - специализация шаблона. Что-то типа такого:

// Generic
template <class Func>
void Foo(Func func)
{
	//if we pass here a int bar(int x);
	// Func will be int(*)(int)
}

// Специализация для Bar
template <>
int Foo<Bar>(int func)
{
	//if we pass here a int bar(int x);
	// Func will be int(*)(int)
}

http://ru.cppreference.com/w/cpp/language/template_specialization

Kroz ★★★★★
()
Ответ на: комментарий от Kroz

Нет, специализации быть не должно. В Foo можно передать любой объект у которого есть operator()

CatsCantFly
() автор топика
Ответ на: комментарий от xaizek

В принципе да, если взять адрес operator(), все получается, проблема только в том, что надо как то отличать просто функции, лямбды и объекты с оператором (). Для функций есть std::is_function, для лямбд идей нет

CatsCantFly
() автор топика
Ответ на: комментарий от anonymous

Чуть компактней и с модным using

template<typename FunctorT> class GetSignature
{
    template<typename ResultT, typename... ParamsT>
    static auto stripClass(ResultT (FunctorT::*)(ParamsT...))
    {
        return static_cast<ResultT(*)(ParamsT...)>(nullptr);
    }
public:
    using type = decltype(stripClass(&FunctorT::operator()));
};
anonymous
()

Итго, для функций и объектов все понятно, и различать их можно. Ключевой вопрос: как в эту схему впихнуть и лямбды еще?

CatsCantFly
() автор топика
Ответ на: комментарий от CatsCantFly
#include <iostream>

int main()
{
    int x = 20;
    auto f1 = []() -> int { return 10; };
    auto f2 = [x]() -> int { return x; };
    auto operator1 = &decltype(f1)::operator();
    auto operator2 = &decltype(f2)::operator();
    std::cout << (f1.*operator1)() << std::endl;
    std::cout << (f2.*operator2)() << std::endl;
    return 0;
}
./foo
10
20
anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.