wyer33
wyer33

Reputation: 6340

How to grab the argument and return types from a std::function with cv and reference qualifiers?

Is there a good way to grab the argument and return types from a std::function such that we also return the cv and reference qualifiers? This partially relates to a previous question here. In any case, using the code in the answer, we have the following example:

#include <functional>
#include <iostream>

template<typename T> 
struct function_traits;

template<typename R, typename ...Args> 
struct function_traits<std::function<R(Args...)>> {
    static const size_t nargs = sizeof...(Args);

    typedef R result_type;

    template <size_t i>
    struct arg {
        typedef typename std::tuple_element<i, std::tuple<Args...>>::type
            type;
    };
};

template <typename T>
void foo(T const & f) {
    typedef function_traits <T> stuff;
    std::cout <<
        typeid(typename function_traits <T>::result_type).name()
        << std::endl;
    std::cout <<
        typeid(typename function_traits <T>::template arg<0>::type).name()
        << std::endl;
    std::cout << typeid(T).name() << std::endl;
}

int main() {
    std::cout << "Function: f" << std::endl;
    auto f = [](double x) { return x+1.;};
    foo <std::function<double(double)>> (f);

    std::cout << std::endl << "Function: g" << std::endl;
    auto g = [](double const & x) { return x+1.;};
    foo <std::function<double(double const &)>> (g);
}

Now, using c++filt, we see the type of f is std::function<double (double)> and the type of g is std::function<double (double const&)>. However, the structure function_traits reports the argument types to be the same, which they are not. Basically, the const& was stripped off the argument type for g. Is there a way to fix this so that const& is retained?

Upvotes: 1

Views: 93

Answers (1)

aschepler
aschepler

Reputation: 72421

The const and reference are stripped off by typeid, not by function_traits. Try adding

std::cout << std::boolalpha << std::is_same<double,
    typename function_traits<T>::template arg<0>::type>::value  << std::endl;
std::cout << std::boolalpha << std::is_same<const double&,
    typename function_traits<T>::template arg<0>::type>::value << std::endl;

to your foo and you'll see the expected values.

Upvotes: 5

Related Questions