No Matching function call to templated function with const parameters - c++

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.

Related

is there anyway pass function as template parameter?

i have been working on a project and i need to know that is there anyway passing a function to template class? lets say i want this to perform sinus or cosinus function
#ifndef INTEGRAL_H
#define INTEGRAL_H
template<class F>
class Integral
{
public:
Integral( F func):f_(func){}
~Integral()=default;
Integral(){
int a,b,N;
double h=(b-a)/N;
sum=0.0;
for (size_t j=0; j<N;++j)
{
sum+=f_(a+j*h); // here i would like to perform sin(a+j*h) or cosinus or somethingelse
}
sum*=h;
}
double Sum(){return sum;}
private:
F f_;
double sum;
};
#endif // INTEGRAL_H
Your code works "as coded" (after a small fix in the constructor, unrelated to the question). But std::sin doesn't name a single function, and you can't pass it into Integral directly. The simplest way is to wrap it into a lambda:
Integral i([](auto arg) { return std::sin(arg); });
double value = i.Sum();
If your compiler doesn't support template argument deduction (available since C++17), you have to be more verbose:
auto my_sin = [](auto arg) { return std::sin(arg); };
Integral<decltype(my_sin)> i(my_sin);
double value = i.Sum();
This might help: Function passed as template argument
In the end, a function is nothing but an address to a particular place in memory which boils down to a simple number and that is something that the template system supports.
However, in your case I would recommend just passing an std::function object which is a glorified function pointer as a regular parameter to your function - omitting the need for a template (at least for this part of the functionality).
is there anyway pass function as template parameter?
Yes. Example:
template<return_type (template_argument_name)(argument_list)>
Another approach is to pass a callable type as template parameter, and invoke an object of that type. This is in fact what you've done in your example.

Why argument conversion is not considered when calling a templated function?

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);

Ambiguous call on glm::slerp

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 ?

How are overloaded functions selected for suitability in C++?

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.

resolve address from overloaded function std::real<float>

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.