a template-argument cannot be a type that contains 'auto' in C++20

In C++20 we are supposed to be able to use concepts like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//type requirement
template<typename T>
concept containerTypes = requires (T t)
{
	typename T::value_type;
	typename T::size_type;
	typename T::allocator_type;
	typename T::iterator;
	typename T::const_iterator;
};

auto max_value(containerTypes auto& cont)	-> typename std::remove_cvref_t<decltype(cont)>::value_type              // this is not OK
{
        typename std::remove_cvref_t<decltype(cont)>::value_type* pp;  // this is OK
	auto x = std::max_element(cont.begin(), cont.end());
	return *x;
}
void useAdd()
{
	std::vector v{ 10,20,30,50 };
	auto m = max_value(v);
}


I get the error in the return type:


a template-argument cannot be a type that contains 'auto'


This error goes away when I remove the trailing return type and leave the compiler to return auto!!

What's happening?

Last edited on
I wonder if it is this:

https://stackoverflow.com/questions/60358154/auto-as-a-template-argument-placeholder-for-a-function-parameter

Also, when one has problems with complex templates, sometimes the answer is to make more use of auto, so if you have removed the trailing return type and just use auto, and it works, why not go with that?
Because I want to know what is wrong!!
Which compiler/os are you using?

PS I get the same error with VS2022 using preview/latest.
Last edited on
I don't know if it should compile or not but at least it compiles with GCC and Clang. https://godbolt.org/z/zjjad86cY
Last edited on
godbolt using VS doesn't compile. So possibly a bug with VS2022. I've had issues with VS concepts previously - where godbolt compiles but VS doesn't. Twice MS agreed it was a problem and fixed it and once stated they adhered to the standard and gcc had an 'extension'.

@JUANDENT I suggest you raise this as an issue with MS (VS/help/SendFeedback/reportaproblem ) and include the godbolt link.
C++20:
1
2
3
4
5
6
7
template < std::ranges::forward_range RANGE >
std::ranges::range_reference_t<RANGE> max_value( RANGE& range )
{
    [[maybe_unused]] std::ranges::range_value_t<RANGE>* ptr = nullptr ; // this is OK
    if( std::ranges::empty(range) ) throw std::invalid_argument("empty");
    return *std::ranges::max_element(range) ;
}

http://coliru.stacked-crooked.com/a/aa052ddfa9f5332f
Registered users can post here. Sign in or register to post.