Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is the type of a function parameter deducible?

I have a class which uses return code:

class MyClass
{
    // ...

public:
    // ValueType get_value() const;               // usual code
    ErrorCode get_value(ValueType& value) const;  // uses error code

   // ...
};

Thus, the second form of get_value() actually provides the value as function parameter, rather than as return value.

Is it possible to deduce the type of the function parameter of get_value(), maybe using decltype?

int main()
{
    // ...

    MyClass my_class;
    // auto val = my_class.get_value();  // okay: value has correct type

    declytype( /* something here */ ) value;
    const auto error = my_class.get_value( value );

    // ...
}
like image 800
nyarlathotep108 Avatar asked Jul 06 '17 14:07

nyarlathotep108


2 Answers

If you want to deduce the type of parameter, you might use templates to do that:

namespace detail
{
    template<typename>
    struct Helper;

    template<typename R, typename C, typename T>
    struct Helper <R(C::*)(T)>
    {
        using type = T;
    };
}

Then use it like:

detail::Helper<decltype(&MyClass::get_value)>::type value;
// ...
const auto error = my_class.get_value(value);

See related question for more details.

like image 87
Edgar Rokjān Avatar answered Nov 02 '22 01:11

Edgar Rokjān


A more compact solution that doesn't require to fully define a new type.

You can use a function declaration (no definition required) and decltype to do that.
It follows a minimal, working example:

#include<type_traits>

template<typename R, typename C, typename T>
constexpr T f(R(C::*)(T));

struct S {
    void f(int) {}
};

int main() {
    static_assert(std::is_same<int, decltype(f(&S::f))>::value, "!");
}

You can also extend it to multiple parameters quite easily by using a tuple:

template<typename R, typename C, typename... T>
constexpr std::tuple<T...> f(R(C::*)(T...));

In C++17 you can also get a more user-friendly type handler using auto template parameter:

template<auto M>
using Type = decltype(f(M));

And use it as:

static_assert(std::is_same_v<int, Type<&S::f>>);
like image 1
skypjack Avatar answered Nov 02 '22 00:11

skypjack