Return type deduction into a template parameter

200 views Asked by At

Is there a way one can do this? As far as I know there isn't since the language does not support it but I wanted to confirm

template <typename Something>
ConceptCheck<auto> return_something(const Something& something) {
    return process_something(something);
}

This would be nice to have in some cases. For example where one wants to document the concepts supported by a return type (which would otherwise be a simple auto, requiring the reader to go elsewhere looking for information).

If this seems like a decent thing to propose, I would like to propose this to the standard for the future, can someone direct me about to how to do so? Are return type concepts already in the C++20 standard?

Thanks!

2

There are 2 answers

2
Mikel F On

You can find just about anything you might want to know about the ongoing standardization effort at https://isocpp.org/

Specifically, https://isocpp.org/blog/2016/12/2016-11-post-issaquah-mailing-available lists all of the documents in the most recent mailing, with the text to the current draft of C++17.

I can tell you that Concepts has not been accepted into the draft standard at this time. That could change in the next meeting, though.

0
skypjack On

You can use a function declaration and a trailing return type to do that.
It follows a minimal, working example (C++14):

#include<type_traits>

template<typename>
struct ConceptCheck {};

template<typename T>
T get_it(ConceptCheck<T>);

ConceptCheck<char> process_something(int) { return {}; }
ConceptCheck<void> process_something(double) { return {}; }

template <typename Something>
auto return_something(const Something& something)
-> ConceptCheck<decltype(get_it(process_something(something)))> {
    return process_something(something);
}

int main() {
    static_assert(std::is_same<decltype(return_something(0)), ConceptCheck<char>>::value, "!");
    static_assert(std::is_same<decltype(return_something(0.)), ConceptCheck<void>>::value, "!");
}

Well, I admit that ConceptCheck<auto> would be nicer than:

ConceptCheck<decltype(get_it(process_something(something)))>

Anyway, if the goal was to document the return type ConceptCheck, no matter what's the actual template parameter, this is a viable solution.

If you don't like the trailing return type or you cannot document it for it's not supported by your documentation tool, you can still use std::declval as it follows:

template <typename Something>
ConceptCheck<decltype(get_it(process_something(std::declval<Something>())))>
return_something(const Something& something) {
    return process_something(something);
}

Or even better:

template <typename Something, typename T = decltype(get_it(process_something(std::declval<Something>())))>
ConceptCheck<T>
return_something(const Something& something) {
    return process_something(something);
}

The extra template parameter is pretty ugly, but the return type is finally ConceptCheck<T>.