Search code examples
c++templatestypesdecltype

How do you use std::declval find the return value of a template function?


I have a class B that takes a template argument such as A. I create a B b and call B::operator()(A a). Regardless of the type of a, b(a) should return a double. I would like to deduce this from outside of B using decltype.

If I had a function B::operator()(), I could do that with

std::declval<B&>()()

This was presented to me in my other question here. (Note, A and B in this question do not match A and B in the previous question.)

If I had a function B::operator()(int i) (no template), I could do that with

std::declval<B>()(int())

although this appears to only work because int is default constructible.

How do I do it when B::operator()() is a template function?

Below is some starting code that compiles on my machine. You shouldn't need to look at it to understand the question.

#include <array>
#include <iostream>
#include <array>

class B {
public:
    B() {};

    template<typename T>
    double operator()(T t) {
        return t();
    }

};

class A {
public:
    A() {};

    double operator()() {
        return 3;
    }
};

int main() {
    A a{};
    B b{};
    std::cout << b(a);

    return 0;
}

Edit:

To clarify, I want to add a line like

using custom_typename = double;

to the above code, except, instead of double, I write something like

using custom_typename = decltype(std::declval<B>()());

modified appropriately to take the return type of B::operator()(T t) instead of B::operator()().


Solution

  • I believe you're looking for

    decltype(std::declval<B>()(std::declval<A>())) c = b(a);
    

    Broken down:

             std::declval<B>() //pretend there's a B object
                               std::declval<A>() //pretend there's an A object
             std::declval<B>()(std::declval<A>()) //call b(a) with these 
    decltype(std::declval<B>()(std::declval<A>())) //tell me the return type
    

    Or, if you wanted to hide that verbosity:

    template<typename T>
    using B_return_t = decltype(std::declval<B>()(std::declval<T>()));
    
    
    B_return_t<A> c = b(a);
    

    http://coliru.stacked-crooked.com/a/4e6e235b47b12cdd

    I assume this doesn't count:

    auto c = b(a);