I have a template function in the style:
template <int Exponent> DERIVED_TYPE pow(TYPE const x);
This function is defined inline in a template struct as a friend function:
template <ARGUMENTS>
struct unit {
typedef unit<ARGUMENTS> type;
....
template <int Exponent>
friend constexpr unit_pow_t<type, Exponent> pow(type const x) { ... }
};
This is because taking a value with a unit to a power has to change the unit along with the value.
When I try to use it omitting the Exponent, I can see the candidates the compiler considers for matching:
src/model/Tool.cpp:113:3: error: no matching function for call to 'pow'
pow(1._m);
^~~
src/model/../units/Units.hpp:2266:46: note: candidate template ignored: couldn't infer template argument 'Exponent'
friend constexpr unit_pow_t<type, Exponent> pow(type const x) {
^
/usr/include/math.h:255:8: note: candidate function not viable: requires 2 arguments, but 1 was provided
double pow(double, double);
^
So far things are as expected, the template is seen, but of course the Exponent needs to be specified. When I do however something unexpected happens:
src/model/Tool.cpp:113:6: error: comparison between pointer and integer ('double (*)(double, double)' and 'int')
pow<3>(1._m);
~~~^~
The compiler sees pow as the address of "double pow(double, double)" and interprets <3 as the intent to compare the function pointer with the integer. The problem occurs with clang 3.4, 3.6 and GCC 5.2.
My question is, how do I convince the compiler that <3> is a template argument list?
UPDATE
I finally managed to create a minimal example, sorry for the incomplete question:
template <int Exp>
struct metre {
double value;
template <int Exponent>
friend constexpr metre<Exp * Exponent> pow(metre<Exp> const x) {
return {0};
}
};
int main() {
pow<2>(metre<1>{1});
return 0;
};
It seems it is not seeing pow:
targs.cpp:11:2: error: use of undeclared identifier 'pow'
pow<2>(metre<1>{1});
^
If I include cmath I have the same diagnostics as before:
targs.cpp:13:5: error: comparison between pointer and integer ('double (*)(double, double)' and 'int')
pow<2>(metre<1>{1});
~~~^~
1 error generated.
So the presence of "double pow(double, double)" just masks the issue that the template is not seen. The question then is, why is pow<>() not seen by the compiler?
There is no need (and no logic) for the friend template
. Use a free function:
template <int Exp>
struct metre {
double value;
};
template<int B, int A>
constexpr auto pow(metre<A> const x) -> metre<A*B>
{
return metre<A*B>{x.value};
}
int main() {
metre<2> result = pow<2>(metre<1>{1});
return 0;
};
Live demo on coliru.
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