user3124812
user3124812

Reputation: 1986

C++ Template; Auto deduction return type of function passed as template argument;

I need to deduct a type of a return value of a getter function. That getter is passed as function pointer in template list.

So getter looks like:

using TGetter   = std::function<std::string(Me*)>;

std::string getter(Me* me)
{
    return std::string("string");
}

Template class

template<typename TGetter>
class Handler
{
public:
    Handler(TGetter getter)
        :m_getter(getter)
    {};

    using TValue =  std::string;  //decltype(TGetter()); <- something like that I want to get

private:
    TGetter                     m_getter;
    ...

    bool handler();

Instantiation is like that:

Handler<TGetter> h(getter);

What I want is to declare TValue depending on getter return type. So std::string as for getter in example. I'm gonna have different types of getters and wand to declare respective type simply like TValue value; inside a class.

using TValue = decltype(TGetter()); is resolved into a function pointer.

Could you help me to get it right, thanks.

Upvotes: 2

Views: 407

Answers (4)

bartop
bartop

Reputation: 10315

Just use std::declval like that if your function has no arguments:

using TValue = decltype(std::declval<TGetter>()(/* your args go here */));

Upvotes: 2

songyuanyao
songyuanyao

Reputation: 172894

You can use std::invoke_result (since C++17).

using TValue = std::invoke_result_t<TGetter, Me*>;

Before C++17 you use std::result_of, note it's deprecated in C++17 and its usage is different with std::invoke_result.

using TValue = std::result_of_t<TGetter(Me*)>;

Upvotes: 2

Jarod42
Jarod42

Reputation: 217145

If you only use std::function, you might do:

template <typename TGetter> class Handler;

template <typename Ret, typename ... Ts>
class Handler<Ret(Ts...)>
{
public:
    using TGetter = std::function<Ret(Ts...)>;

    Handler(TGetter getter) : m_getter(getter) {}

    using TValue = Ret;

private:
    TGetter                     m_getter;
    // ...

    bool handler();
};

with usage such as Handler<std::string(Me*)> h(&getter);

If you want any callable type, then:

template <typename TGetter>
class Handler
{
public:
    Handler(TGetter getter) : m_getter(getter) {}

    using TValue = decltype(declval<TGetter>()(/*args*/));

private:
    TGetter                     m_getter;
    // ...

    bool handler();
};

Upvotes: 2

zdf
zdf

Reputation: 4808

What you are looking for is result_type, probably:

//...
public:
  using TValue =  typename TGetter::result_type;
//...

Demo.

Upvotes: 1

Related Questions