Can I use constrained generic types inside C++20 constraints for a concept? As an example, say I'd like to write a requirement that a candidate class T have a function func that can take an argument of any type that satisfies std::ranges::range:
template<typename T>
concept Foo = requires (T t, std::ranges:range s) {
{ t.func(a); } -> std::convertible_to<double>;
}
But GCC gives me an error message that a placeholder type cannot be used where I've put std::ranges::range.
It seems to me that your looking a struct with an (declared only) operator T () for a generic T
struct generic_argument
{
template <typename T>
operator T () const;
};
so you can pass it (inside a decltype()) for every expected argument and also a template argument.
So your concept (sorry... I simplify it removing the ranges argument) become (if I understand what do you want) something as
template<typename T>
concept Foo
= std::convertible_to<decltype(std::declval<T>().func(std::declval<generic_argument>())),
double>;
The following is a full compiling example
#include <iostream>
struct A { double func (int a) { return a; } };
struct B { double not_func (long a) { return a; } };
struct C { std::string func (char) { return "abc"; } };
struct D { float func (auto) { return 1.0f; } };
struct E { double func (int a) { return a; }
std::string func (char) { return "abc"; } };
struct generic_argument
{
template <typename T>
operator T () const;
};
template<typename T>
concept Foo
= std::convertible_to<decltype(std::declval<T>().func(std::declval<generic_argument>())),
double>;
template <Foo T>
void bar (T const &)
{ std::cout << "bar, Foo version\n"; }
template <typename T>
void bar (T const &)
{ std::cout << "bar, generic version\n"; }
int main()
{
bar(A{}); // print bar, Foo version
bar(B{}); // print bar, generic version [no func() function]
bar(C{}); // print bar, generic version [no convertible to double]
bar(D{}); // print bar, Foo version
bar(E{}); // print bar, generic version [two func() function]
}
I'm in doubt regarding the E case: two func() methods, one only return a type convertible to double, from bar(E{}) we get "bar, generic version".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With