The error is (using VS2013 - GLM):
more than one instance of overloaded function "glm::slerp" matches the
argument list: function template "glm::detail::tquat
glm::slerp(const glm::detail::tquat &x, const glm::detail::tquat
&y, const T &a)" function template "T glm::slerp(const
glm::detail::tquat &x, const glm::detail::tquat &y, const T &a)"
argument types are: (glm::quat, glm::quat, float)
I'm calling it with two glm::quat and a constant float value, just like you would do with glm::lerp and glm::mix. The two overloaded functions shown in the error message only differs on the return type. I've been searching for an answer without any luck.
The exact call:
const float t = 0.5f;
glm::quat newQ = glm::slerp(quatA, quatB, t);
It is impossible (hear illegal) in C++ to have function definitions that differs only by return type because the return type is not part of the signature, and therefore will violate one definition rule.
I suggest you write the template parameters explicitely, or cast to something you are sure ?
Related
I have a template class and a friend operator* function
StereoSmp<TE> operator* (const StereoSmp<TE>& a, TE b)
I use it with TE=float but I need to multiply a StereoSmp<float> * double
I think that should be possibile because it should converts double to float automatically and works but I get the error:
no match for ‘operator*’ (operand types are ‘StereoSmp<float>’ and
‘__gnu_cxx::__alloc_traits<std::allocator<double> >::value_type {aka double}’)
deduced conflicting types for parameter ‘TE’ (‘float’ and ‘double’)
Why it doesn't convert double to float automatically? And what can I do to allow the automatic conversion between types?
Don't make your friend a template.
template<class TE>
struct StereoSmp {
friend StereoSmp operator* (const StereoSmp& a, TE b) {
return multiply( a, b ); // implement here
}
};
this is a non-template friend to each type instance of the template StereoSmp. It will consider conversions.
Template functions don't consider conversions, they simply do exact pattern matching. Overload resolution is already insane enough in C++.
Keep it simple, silly:
template<class U>
StereoSmp<TE> operator* (const StereoSmp<TE>& a, U b);
or if it applies:
StereoSmp<TE> a {/* ... */};
double b = /* ... */;
auto c = a * static_cast<float>(b);
Why it doesn't convert double to float automatically?
Because template deduction happens before possible conversions are taken into consideration. If you call a*b with a a StereoSmp<float> and b a double, template substitution will fail before a float to double conversion can be considered, and name lookup will continue, until failing short of candidates.
This process is called Template argument deduction.
Although Yakk's answer is probably the best in this particular scenario, I want to point out that you can prevent this deduction conflict and get your expected result (pass StereoSmp<float>, deduce TE as float) by making the other argument ineligible for use in deduction:
StereoSmp<TE> operator* (const StereoSmp<TE>& a, remove_reference<TE>::type b)
Related reading: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3766.html
Why it doesn't convert double to float automatically? And what can I do to allow the automatic conversion between types?
This isn't a conversion problem, it's a template parameter inference issue. Since the declaration is of the form:
StereoSmp<TE> operator* (const StereoSmp<TE>& a, TE b)
... and the operands are of type StereoSmp<float> and double, the C++ inference rules do not work, because they do not take into account that a double is convertible to a float. These rules are specified by the language specification; the reason why they don't take potential conversions into account is probably because "it would make deduction very complicated, otherwise". The rules are already complex enough!
You can of course cast your double parameter to a float and it will work fine. Also, you could make the operator* a member function of StereoSmp, or you could independently parameterise the types of the type parameters:
template <class TE, class U> StereoSmp<TE> operator* (const StereoSmp<TE>& a, U b);
I need some help understanding how overloaded C++ functions are selected by the compiler.
When given a function:
type func(type1 x, type2 y);
type func(type3 x, type2 y);
How does the compiler determine which function to choose?
I know the function chosen is according to its suitability, but how to you know which function is chosen if either could be used successfully.
For example:
Given these function overloaded functions:
char* average(int i, float f, double d);
double average(double d, float f, int i);
double fabs(double d);
Given these variables:
int i1, i2, i3;
float f1, f2, f3;
What data type is the return value of these function calls? and why?
average(i1, i2, i3);
average(f1, f2, f3);
fabs(average(f1,f2,f3));
The return value depends on the function call that is made. For example your first function call would return value double because second average function is called.
The function overloading solely takes place on basis of arguments irrespective of return types. You can't overload two functions solely on basis that they have different return types. The functions should differ by arguments in order for function overloading to work.
In order to compile a function call, the compiler must first perform name lookup, which, for functions, may involve argument-dependent lookup(ADL).
If these steps produce more than one candidate function, then overload resolution is performed to select the function that will actually be called.
In general, the candidate function whose parameters match the arguments most closely is the one that is called.
As in your case:
1--> char* average(int i, float f, double d);
2--> double average(double d, float f, int i);
Here in both of your functions you have completly different argument list. 1st average is taking int, float, double and the 2nd one is double, float, int.
So, compiler decides which method to invoke first based in its arguments.
If you invoke method with argument (int, float, double) the overloaded version takes 1st method and if you invoke method with argument (double, float, int) the overloaded version takes 2nd method.
The choice if which overloaded method to call(in other words, the signature of the method) is decided at compile time.
So, compiler will already know the signature of the method to be invoked.
While overloading methods we must keep the following rules in mind:
Overloaded methods MUST change the argument list,
Overloaded methods CAN change the return types.
Overloaded methods CAN change the access modifier.
A method can be overloaded in the same class or in a subclass.
I am working with a member function that just sets the object's internal orientation to the values given in the argument:
void A::SetOrientation(float a[3]);
In another class, I have the following:
class B
{
public:
RestoreStateTo(A* const o_pA) const
private:
float d_orientation[3];
};
void
B::RestoreStateTo(A* const o_pA) const
{
o_pA->SetOrientation(d_orientation);
}
I get the following compiler error (with Visual Studio 2010):
error C2664: 'void A::SetOrientation(float [])' : cannot convert parameter 1 from 'const float [3]' to 'float []'
I found that I can avoid the issue with o_pA->SetOrientation(const_cast<float *>(d_orientation));, but I'd like to get a better grasp of what is going on.
I would appreciate an explanation as to why the array argument is converted to a const array as well as suggest the right approach to dealing with the error?
Because the prototype of your function void B::RestoreStateTo(A* const o_pA) const says you will not modify any member of B.
Since d_orientation is an attribute of B, it is const in this function.
Your SetOrientation function should take in a const,
void A::SetOrientation(const float a[3]);
Otherwise, it's possible that A::SetOrientation will modify the array you pass in. Because you have "B::RestoreStateTo(A* const o_pA) const", it means that the compiler won't let you pass a pointer to B::d_orientation as a non-const input, because A::SetOrientation has no guarantee not to modify it.
You have declared a const member function, and therefore all the members of this will be treated as const inside that function. So it shouldn't be surprising that d_orientation is treated as const.
It's the same principle that makes this code illegal:
const B* p = ...;
p->d_orientation[0] = 0.0f; // error, assigning member of `const` object
std::vector<std::complex<float> > c;
std::vector<float> d;
std::transform(c.begin(), c.end(), d.begin(), std::real<float>);
Why couldn't the compiler resolve the address from the overloaded function real<float>?
Which overloaded functions does the compiler mean?
Your library implementation has provided additional overloads for std::real<float>.
Why the overloads?
26.4.9 Additional overloads [cmplx.over]
1 The following function templates shall have additional overloads:
arg norm
conj proj
imag real
2 The additional overloads shall be sufficient to ensure:
If the argument has type long double, then it is effectively cast to complex<long double>.
Otherwise, if the argument has type double or an integer type, then it is effectively cast to complex<double>.
Otherwise, if the argument has type float, then it is effectively cast to complex<float>.
[...]
Solutions to problem:
You could just use a range based for ...
for (auto v : c) d.push_back(real(v));
... or pack the call to real into a functor or another function ...
struct my_caller {
template <typename T> T operator() (std::complex<T> const &c) {
return real(c);
}
};
... or use the member function ...
std::transform(c.begin(), c.end(), d.begin(), [](std::complex<T> const &c) {
return c.real();
});
IMPORTANT:
Note that you have to have enough space in the target when using transform:
std::vector<float> d (c.size());
or use a back inserter:
std::transform(c.begin(), c.end(), back_inserter(d), ...);
Otherwise you are iterating over undefined memory, yielding undefined behaviour.
§26.4.9 states that (amongst others), real shall have additional overloads, for arguments of type float, double and long double. It seems your libraray implementation made a template for these overloads, maybe like
template <typename T>
T real(T const& t)
{
return std::real(std::complex<T>{t});
}
In addition to the solutions phresnel priovided, you could explicitly tell the compiler which kind of function pointer you mean:
std::transform(c.begin(), c.end(), d.begin(), (float(*)(std::complex<float> const&))std::real<float>);
The compiler then looks for a std::real that can be converted into a function pointer of the given type and will find the correct one.
I tell you this only for completeness - I consider this explicit cast ugly and would prefer the ranged based for or transform with a lambda.
I have a function that is defined as follows:
template < class T> T doSomething(const T value, const T value2, const T value3)
{
T temp = value;
//Do stuff
return temp ;
}
in my main, I go to call it as follows:
doSomething(12.0, 23.0f, 2.0f);
I get an error saying no matching function for call doSomething(double, float, float).
I tried to used const_cast but it didn't seem to fix the issue. Any help would be appreciated.
It's not about the const, but about that T cannot be both double and float at the same time.
If you have a non-template function, one or more parameter can be promoted (or converted) to the parameter type. With a template function, the compiler will have to start by determining what the template type is supposed to be. Here it cannot decide.
Your function definition uses same type "T" for every of three arguments.
C++ is not able to deduct types in cases like this.
Please choose way to fix:
Different types for every argument
template<typename A, typename B, typename C>
A doSomething(const A& value, const B& value2, const C& value3)
{
A temp = value;
//Do stuff
return temp ;
}
Explicit template argument on call:
doSomething<int>(12.0, 23.0f, 2.0f);
Explicit type cast for argument on call:
doSomething(12.0, static_cast<double>(23.0f), static_cast<double>(2.0f));
When using a templated function, you need to supply the template parameters within angle brackets.
I.e. you need to use doSomething<float>(12.0, 23.0f, 2.0f);
Or, at least, if you don't, the compiler has to guess what T is, which means when it sees a double for the first argument it assumes you mean doSomething<double>()
When you call like this:
doSomething(12.0, 23.0f, 2.0f);
then you basically let the compiler to deduce the template argument T, from the function arguments. But in the above call, type of all arguments are not same : the first argument12.0 is double, while the rest two arguments are float (Note that f in 2.0f makes it a float, while 2.0 is a double.). Hence the problem, as the compiler is trying to find a function which accepts double, float, float as arguments. But there is no such function. And the function template cannot be deduced from the arguments, because T has to be same for all arguments.
So the solution is, let T be deduced as either double or float:
doSomething(12.0f, 23.0f, 2.0f); //all are float now
Or this:
doSomething(12.0, 23.0, 2.0); //all are double now
In the first case, T is deduced as float, and in the second case, T is deduced as double.
Alternately, you may choose not to depend on template argument deduction, by providing template argument as:
doSomething<float>(12.0, 23.0f, 2.0f);
Or this:
doSomething<double>(12.0, 23.0f, 2.0f);
Here, in the first case, the 1st argument converts into float, and in the second case, 2nd and 3rd argument convert into double.