I have a C++ macro that I want to use to call a function template which is overloaded. I want one of these function templates to only accept floating point values and the other function template will accept everything else.
Here is the code that I run in https://cpp.sh/ with C++ 20:
#include <iostream>
#include <string>
#include <vector>
#include <type_traits>
#include <concepts>
template< typename T>
concept NotFloatingPoint = requires
{
!std::is_same_v<T, double> || !std::is_same_v<T, float>;
};
template< NotFloatingPoint T, NotFloatingPoint U, bool isDistanceType_ = false >
void ProcConstantConfigForce( T& value_ )
{
std::cout << "Inside ProcConstantConfigForce()\n";
std::cout << value_;
}
template< typename T>
concept FloatingPoint = requires
{
std::is_same_v<T, double> || std::is_same_v<T, float>;
};
template< FloatingPoint T, FloatingPoint U, bool isDistanceType_ = false >
void ProcConstantConfigForce( T& value_ )
{
std::cout << "Inside ProcConstantConfigForce() for doubles\n";
std::cout << value_;
if ( isDistanceType_ )
{
value_ *= 1.5;
}
}
#define FORCE_CONSTANT( constant_, isDistanceType_ ) ProcConstantConfigForce< decltype( constant_ ), decltype( constant_ ), isDistanceType_ >
int main()
{
double val = 1.0;
FORCE_CONSTANT(1.0, true)(val);
std::cout << "Updated val: " << val;
}
However, the compiler complains about it being ambiguous:
main.cpp:43:3: error: call to 'ProcConstantConfigForce' is ambiguous
FORCE_CONSTANT(1.0, true)(val);
^~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:38:54: note: expanded from macro 'FORCE_CONSTANT'
#define FORCE_CONSTANT( constant_, isDistanceType_ ) ProcConstantConfigForce< decltype( constant_ ), decltype( constant_ ), isDistanceType_ >
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:14:6: note: candidate function [with T = double, U = double, isDistanceType_ = true]
void ProcConstantConfigForce( T& value_ )
^
main.cpp:27:6: note: candidate function [with T = double, U = double, isDistanceType_ = true]
void ProcConstantConfigForce( T& value_ )
^
1 error generated.
I have found that I can solve my problem using constexpr with the std::floating_point concept and just use a single function template. However, I specifically want to know why the compiler complains that it is ambiguous since it is clear that only one function should be used for floating point values so why does it try to instantiate a template of the first function when the concept should restrict it?
thank you for the help.
There are two problems with your code. First,
doesn't do what you think it does:
requires { expr; }
checks whetherexpr
is a valid expression, not whetherexpr
is true. So you should rewrite this asBut it's still incorrect. It now checks whether one of two things is true:
T
is notdouble
, orT
is notfloat
. That means that even ifT
isdouble
, it still satisfiesNotFloatingPoint
becausedouble
is notfloat
. It's impossible forNotFloatingPoint
to ever be false. The correct definition is:Or an easier way might be: