I want to have a helper function that helps me to get the value or the value of the pointee when its a pointer.
For example, I want to substract a pair numerical values or the values for the types that defines an overload for the - operator.
This is my code:
template <typename T>
T value_retriever(const T&& val) {
if constexpr (std::is_pointer_v<decltype(val)> || std::is_reference_v<decltype(val)>)
return *val;
else
return std::forward<T>(val);
}
template <typename T>
[[nodiscard]] constexpr auto minus(const T&& lhs, const T&& rhs) -> T {
return value_retriever(std::move(lhs)) - value_retriever(std::move(rhs));
}
And this are the errors that I am facing:
In module 'math' imported from zero\main.cpp:8:
In module 'math.ops' imported from zero/ifc/math/math.cppm:3:
zero/ifc/math/ops/arithmetic.cppm:25:16: error: cannot initialize return
object of type 'const int *' with an rvalue of type 'long long'
return value_retriever(std::forward<T>(lhs)) - value_retriever(std::forward<T>(rhs));
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
zero\main.cpp:38:83: note: in instantiation of function template
specialization 'zero::math::minus<const int *>' requested here
std::cout << "Subtraction of two integer l-value references: " << zero::math::minus(&a, &b) << "\n\n";
^
In module 'math' imported from zero\main.cpp:8:
In module 'math.ops' imported from zero/ifc/math/math.cppm:3:
zero/ifc/math/ops/arithmetic.cppm:9:20: error: indirection requires pointer
operand ('int' invalid)
return *val;
^~~~
zero/ifc/math/ops/arithmetic.cppm:25:16: note: in instantiation of function
template specialization 'zero::math::value_retriever<int>' requested here
return value_retriever(std::forward<T>(lhs)) - value_retriever(std::forward<T>(rhs));
^
zero/ifc/math/ops/arithmetic.cppm:9:20: error: cannot initialize return
object of type 'const int *' with an lvalue of type 'const int'
return *val;
^~~~
zero/ifc/math/ops/arithmetic.cppm:25:16: note: in instantiation of function
template specialization 'zero::math::value_retriever<const int *>' requested here
return value_retriever(std::forward<T>(lhs)) - value_retriever(std::forward<T>(rhs));
^
3 errors generated.
The call site:
const int a = 16;
const int b = 20;
std::cout << "Subtraction of two integers, passed as l-value references: " << zero::math::minus(&a, &b) << "\n\n";
I am failing to understand certain things about universal references.That's clear. But the error that is making me mad is this:
indirection requires pointer
operand ('int' invalid)
return *val;
if constexpr
branch detected that val
is a ptr or a reference, how can I have an error that says that `indirection requires ptr operand?T
?Supposed you want to instantiate the function template for int
then this branch makes no sense:
if constexpr (std::is_pointer_v<decltype(val)> || std::is_reference_v<decltype(val)>)
return *val;
A reference to an int
has no operator*
.
The forwarding reference is a red herring. The error is not related to using a forwarding reference, and you do not need a forwarding reference when dealing with either int
or int*
.
Here is how you can do it:
#include <iostream>
template <typename T>
auto value_retriever(T& val) {
if constexpr (std::is_pointer_v<T>)
return *val;
else
return val;
}
template <typename T>
[[nodiscard]] constexpr auto minus(const T& lhs, const T& rhs) -> std::remove_pointer_t<T> {
std::cout << value_retriever(lhs) << " - " << value_retriever(rhs) << "\n";
return value_retriever(lhs) - value_retriever(rhs);
}
int main() {
int x = 42;
int y = 40;
std::cout << minus(&x,&y) << "\n";
std::cout << minus(x,y) << "\n";
}