I've returned to c++ after many years and trying to grasp the concepts. I've written a simple test code, but I'm getting an error which I don't really understand why it is here.
template <typename T, typename U>
concept addable = requires (T a, U b)
{
a + b;
};
template <typename T>
T test_add(T&& value)
{
return value;
}
template <typename T, typename... Args>
auto test_add(T&& value, Args&&... rest) requires addable<T, decltype(test_add(forward<Args>(rest)...))>
{
return value + test_add(forward<Args>(rest)...);
}
The goal is to check if there is a valid + operation on the returning expression, but when i call the function like this:
auto result = test_add(1, 3, 5);
I get following error: "no instance of overloaded function "test_add" matches the argument list".
What is wrong here?
It looks like you want the concept
to be variadic, so you need a parameter pack and then a fold expression over the +
operator:
template <class... Ts>
concept addable = requires(Ts&&... ts) { (... + ts); };
// ^^^^^^^^
// fold over +
Your test_add
function templates could then be replaced with one that uses the concept
(with a similar fold expression):
auto test_add(addable auto&&... values) {
return (... + std::forward<decltype(values)>(values));
}
If you want two separate function templates, you can (with the same concept
as above). You mainly need to change what you put in as a requirement:
template <typename T>
decltype(auto) test_add(T&& value) {
return std::forward<T>(value);
}
template <typename T, typename... Args>
auto test_add(T&& value, Args&&... rest)
requires addable<T, Args...>
// ^^^^^^^^^^^^^^^^^^^
{
return std::forward<T>(value) + test_add(std::forward<Args>(rest)...);
}