arma::Mat<double> (*Sum)(arma::Mat<double>, int) = arma::sum; // The function pointer to arma::sum
arma::Mat<double> mat = Sum(A, 1); //A is of type arma::Mat<double>
std::cout<<mat;
produces the error :
error: no matches converting function ‘sum’ to type ‘class arma::Mat<double> (*)(class arma::Mat<double>, int)’
arma::Mat<double> (*Sum)(arma::Mat<double>, int) = &arma::sum;
I'm unable to understand this as
arma::Mat<T> mat;
mat = arma::sum(this->data, 1);
std::cout<<mat;
produces the desired result when the template T is of type double.Please help me out,thanks!!
The prototype for arma::sum in Armadillo documentation is given as:
sum( M )
sum( M, dim ) //dim = 0, 1 for rowise or columnwise sum
Just because the result can be assigned to a variable of a certain type, that doesn't mean that, that is the signature of the method.
A function can return a type which can be converted or assigned to a variable of another type.
In this case, to solve the problem - the original function has to be checked for it's signature (in the header files).
Then it will be possible to create the correct signature, expecially if there are overloads of the function.
For example, a signature from the Armadillo project:
template<typename T1>
arma_warn_unused
arma_inline
const Op<T1, op_sum>
sum
(
const T1& X,
const uword dim = 0,
const typename enable_if< is_arma_type<T1>::value == true >::result* junk1 = 0,
const typename enable_if< resolves_to_vector<T1>::value == false >::result* junk2 = 0
)
// ignore the implemenation ...
As can be seen this function returns an Op type which is a template class. The function has 2 usefull for the user parameters and 2 metaprogramming parameters, used by the implementation.
If you call this function with the type arma::Mat<double> then the signature of this chosen function is:
const Op<arma::Mat<double>, op_sum> (*sum_func)(const arma::Mat<double>, const uword, const void*, const void*)
As I can see in the header file, 11 definitions for sum function are provided. Then also metaprogramming is used to improve the performance of the implementation, which also increases the amount of combinations of parameters for this function, which means even more definitions.
So the type of this function is actually quite compilcated. And because of the metaprogramming it is not necassarily the one which is used, when it is called.
To help with the deduction of the return type decltype can be used.
class Test
{
public:
int sum (int i){return 1;}
float sum (float i){return 2.0;}
};
int main()
{
Test t;
decltype(t.sum(0)) (Test::* sum_ptr)(int) = &Test::sum;
return (t.*sum_ptr)(0);
}
I keep a helper function around just for this kind of cases, whare you want to resolve an overload without caring about the return type:
template <class... Params, class R>
auto ovl(R(*f)(Params...)) {
return f;
}
Your initialization then becomes:
auto Sum = ovl<arma::Mat<double>, int>(arma::sum);
Related
I am in the process of fixing some of the sonarcloud issues on my project. One complaint is the function where I read and deserialize the settings for my application. Basically there are 50 or so blocks of this in one function:
if (!m_logLevel.deserializeFromSettings(settings, HGGW_KEY_LOGLEVEL) || m_logLevel.value() <= 0 || m_logLevel.value() > 4)
{
m_logLevel.update(HGGW_DEFAULT_LOGLEVEL, 0);
m_logLevel.serializeToQSettings(settings, HGGW_KEY_LOGLEVEL);
}
The members are instances of a templated class:
template <typename T>
class AwsProperty
{
public:
AwsProperty(T value, qint64 timestamp) : m_timestamp(timestamp), m_data(value){}
//other stuff, not important
}
//example:
AwsProperty<int> m_property;
I tried to design this function:
template <typename X>
void readAWSSettingOrPopulateDefault(AwsProperty<X> property, QString key, X default_val, QSettings settings, bool (*predicate)(X)){
if(!property.deserializeFromSettings(settings,key) || predicate(property.value())){
property.update(default_val, 0);
property.serializeToQSettings(settings, key);
}
}
Trying to call it:
this->readAWSSettingOrPopulateDefault(m_logLevel, HGGW_KEY_LOGLEVEL, HGGW_DEFAULT_LOGLEVEL, settings, [](int val){return val <= 0 || val > 4;});
Yields this error:
XXXXconfig.cpp:275: error: no matching function for call to ‘LocalConfig::readAWSSettingOrPopulateDefault(HGGWAwsPropertyInt32&, const QString&, const int&, QSettings&, LocalConfig::init(QString)::<lambda(int)>)’
this->readAWSSettingOrPopulateDefault(m_logLevel, HGGW_KEY_LOGLEVEL, HGGW_DEFAULT_LOGLEVEL, settings, [](int val){return val <= 0 || val > 4;});
XXXXconfig.cpp:275: note: mismatched types ‘bool (*)(X)’ and ‘LocalConfig::init(QString)::<lambda(int)>’
this->readAWSSettingOrPopulateDefault(m_logLevel, HGGW_KEY_LOGLEVEL, HGGW_DEFAULT_LOGLEVEL, settings, [](int val){return val <= 0 || val > 4;});
^ ^
XXXXconfig.cpp:275: note: mismatched types ‘bool (*)(X)’ and ‘LocalConfig::init(QString)::<lambda(int)>’
^
The reason your code reports an error is that for a function template declared as:
template <typename X>
void readAWSSettingOrPopulateDefault(AwsProperty<X> property, QString key
, X default_val, QSettings settings
, bool (*predicate)(X));
the compiler will have to deduce X from all arguments using this template parameter -- property, default_val and predicate -- and then make sure that those deduced types are the same (that is, there's only one template parameter, it can hold one type).
However, a lambda is not a function. It is convertible to a function pointer through an implicit conversion. Template argument deduction does not consider conversions (except for the derived-to-base conversion). Hence, the compiler is unable to finalize template argument deduction.
In order to make your code work, put the last occurrence of X in the function pointer-type parameter declaration in a non-deduced context:
template <typename T>
struct dont_deduce { using type = T; };
template <typename T>
using dont_deduce_t = typename dont_deduce<T>::type;
template <typename X>
void readAWSSettingOrPopulateDefault(AwsProperty<X> property, QString key
, X default_val, QSettings settings
, bool (*predicate)(dont_deduce_t<X>));
This way, the compiler will not even attempt to deduce X from the lambda expression, and instead will use the type from property/default_val, thus making it possible to use the implicit conversion of the lambda to a function pointer. That is, no deduction and at the same time, a known function signature that can trigger the conversion.
Consider the following code:
#include <iostream>
float func(char const & val1, unsigned int const & val2)
{
return val1 + val2;
}
int main() {
double test1 = 0.2;
double test2 = 0.3;
std::cout << func(test1, test2) << std::endl;
return 0;
}
This compiles and runs despite the fact that I am passing in a double to a function that takes a const-reference to types that are smaller than a double (on my system, sizeof(double) == 8, while sizeof(unsigned int) == 4, and sizeof(char) == 1 by definition). If the reference isn't const, compilation fails (e.g., float func(char & val1, unsigned int & val2) instead of the current definition) with an error:
cannot bind non-const lvalue reference of type 'char&' to an rvalue of type 'char'
I get the exact same behavior when testing this with GCC, Clang, ICC, and MSVC on Godbolt, so it appears standard. What is it about const-references that causes this to be accepted, whereas a reference isn't? Also, I used -Wall -pedantic - why am I not getting a warning about a narrowing conversion? I do when the function passes by value instead of by reference...
It is indeed standard.
test1 and test2 are converted to anonymous temporary char and unsigned types for which the const references in the function are appropriate bindings. If you set your compiler to warn you of narrowing conversions (e.g. -Wconversion), it would output a message.
These bindings are not possible if the function parameters are non-const references, and your compiler is correctly issuing a diagnostic in that case.
One fix is to delete a better overload match:
float func(double, double) = delete;
As a complement to the accepted answer, particularly the approach
One fix is to delete a better overload match:
float func(double, double) = delete;
one could also approach it from the other way around: namely deleting all overloads that are not exactly matching your intended types of parameters. If you want to avoid any implicit conversions (including promotions), you could define func as a deleted non-overloaded function template, and define explicit specializations of func only for the specific types of arguments you’d like to have overloads for. E.g.:
// Do not overload the primary function template 'func'.
// http://www.gotw.ca/publications/mill17.htm
template< typename T, typename U >
float func(const T& val1, const U& val2) = delete;
template<>
float func(char const& val1, unsigned int const& val2)
{
return val1 + val2;
}
int main() {
double test1 = 0.2;
double test2 = 0.3;
char test3 = 'a';
unsigned int test4 = 4U;
signed int test5 = 5;
//(void)func(test1, test2); // error: call to deleted function 'func' (... [with T = double, U = double])
//(void)func(test2, test3); // error: call to deleted function 'func' (... [with T = double, U = char])
(void)func(test3, test4); // OK
//(void)func(test3, test5); // error: call to deleted function 'func' (... [with T = char, U = int])
return 0;
}
Emphasizing again to take care if intending to overload the primary function template, as overload resolution for overloaded and explicitly specialized function templates can be somewhat confusing, as specializations do not participate in the first step of overload resolution.
template < class A, class B, class R = A >
void addMultiplyOperation( std::function< R ( const A&, const B& ) > func )
{
...
}
addMultiplyOperation< float, int >( []( float a, int b ) { return a * b; } );
This gives the compiler error:
In function 'int main(int, char**)':
error: no matching function for call to 'addMultiplyOperation(main(int, char**)::__lambda1)'
addMultiplyOperation< float, int >( []( float a, int b ) { return a * b; } );
^
note: candidate is:
note: template<class A, class B, class R> void addMultiplyOperation(std::function<R(const A&, const B&)>)
void addMultiplyOperation( std::function< R ( const A&, const B& ) > func )
^
note: template argument deduction/substitution failed:
note: 'main(int, char**)::__lambda1' is not derived from 'std::function<R(const float&, const int&)>'
addMultiplyOperation< float, int >( []( float a, int b ) { return a * b; } );
^
Despite having the R template argument default initialised to A, I have to provide the third argument in order for this to compile. Is there something else I have to do in order to use default template arguments?
I'm using g++ v4.8.1.
Despite having the R template argument default initialised to A, I have to provide the third argument in order for this to compile.
Actually, this has nothing to do with the fact that it's a default argument. The compiler can't deduce A and B either. Take a look at this simple example:
template<class A>
void f(function<void(A)> f) { }
int main() {
auto lambda = [](){};
f(lambda);
}
You'd think this would be super easy, and A should be deduced as void. But nope, it can't be done. When deducing template parameters, the compiler doesn't consider what constructors the parameter type would have for each possible combination of template parameters. It would be intractable to perform this sort of deduction in general.
For now, you'll just have to make addMultiplyOperation accept any type, and hope it's callable...
template<class Function>
void addMultiplyOperation(Function func) {
// ....
}
If necessary, there are ways to deduce the types of the arguments that the function object can accept, for example as described in this answer: Is it possible to figure out the parameter type and return type of a lambda?
This will lead to some nasty compilation errors if the object passed in is not actually callable, or takes the wrong number of arguments. For now I'm not sure whether there's a nice way to solve this. Concepts, coming in C++14, should alleviate some of these issues.
I'm trying to pass an overloaded function pointer to template function as a parameter.
float Function1(float par1)
{
return 0;
}
float Function1(float par1, float par2)
{
return 0;
}
template<typename R, typename A1>
void Bind(R(*func)(A1))
{
std::cout << "Correct one called\n";
}
template<typename R, typename A1, typename A2>
void Bind(R(*func)(A1, A2))
{
std::cout << "False one called\n";
}
int main()
{
Bind<float, float>(&Function1);
}
Even tho i call the function with 2 float parameters explicity, compiler can't seem to resolve the correct call.
Compiler shows an 'ambiguous function call' error.
I have created a small sample here:
http://liveworkspace.org/code/4kVlUY$195
What's the cause of this error?
Thank you.
The ambiguity comes when you try to take Function1's address. The compiler sees 2 overloads and it can't know which one you're referring to. You need to explicitly indicate which one you want:
Bind(
static_cast<float(*)(float, float)>(&Function1)
);
You're indicating template arguments explicitly on the call to Bind, but that's too late, the ambiguity was found before that point.
You need to resolve the ambiguity manually, such as with a cast expression.
Bind<float, float>( static_cast< float (*)(float par1, float par2)>( &Function1 ));
According to the error message, it's not Function1 that's ambiguous, it's Bind.
Compilation finished with errors:
source.cpp:31:4: error: call to 'Bind' is ambiguous
Bind<float, float>(&Function1);
^~~~~~~~~~~~~~~~~~
source.cpp:18:6: note: candidate function [with R = float, A1 = float]
void Bind(R(*func)(A1))
^
source.cpp:24:6: note: candidate function [with R = float, A1 = float, A2 = float]
void Bind(R(*func)(A1, A2))
The problems is that you specified two arguments, <float, float>, but that doesn't exclude the possibility of a third argument which is automatically deduced. C++ allows for explicit and implicit arguments to the same function template call!
Another solution is to force it to resolve the template name without considering implicit arguments. This works too, but it's more hackish:
(*&Bind<float, float>)(&Function1); // Taking address first hides arguments from deduction
This is probably going to be a really simple explanation, but I'm going to give as much backstory as possible in case I'm wrong. Advanced apologies for being so verbose. I'm using gcc4.5, and I realize the c++0x support is still somewhat experimental, but I'm going to act on the assumption that there's a non-bug related reason for the behavior I'm seeing.
I'm experimenting with variadic function templates. The end goal was to build a cons-list out of std::pair. It wasn't meant to be a custom type, just a string of pair objects. The function that constructs the list would have to be in some way recursive, with the ultimate return value being dependent on the result of the recursive calls. As an added twist, successive parameters are added together before being inserted into the list. So if I pass [1, 2, 3, 4, 5, 6] the end result should be {1+2, {3+4, 5+6}}.
My initial attempt was fairly naive. A function, Build, with two overloads. One took two identical parameters and simply returned their sum. The other took two parameters and a parameter pack. The return value was a pair consisting of the sum of the two set parameters, and the recursive call. In retrospect, this was obviously a flawed strategy, because the function isn't declared when I try to figure out its return type, so it has no choice but to resolve to the non-recursive version.
That I understand. Where I got confused was the second iteration. I decided to make those functions static members of a template class. The function calls themselves are not parameterized, but instead the entire class is. My assumption was that when the recursive function attempts to generate its return type, it would instantiate a whole new version of the structure with its own static function, and everything would work itself out.
The result was: "error: no matching function for call to BuildStruct<double, double, char, char>::Go(const char&, const char&)"
The offending code:
static auto Go(const Type& t0, const Type& t1, const Types&... rest)
-> std::pair<Type, decltype(BuildStruct<Types...>::Go(rest...))>
My confusion comes from the fact that the parameters to BuildStruct should always be the same types as the arguments sent to BuildStruct::Go, but in the error code Go is missing the initial two double parameters. What am I missing here? If my initial assumption about how the static functions would be chosen was incorrect, why is it trying to call the wrong function rather than just not finding a function at all? It seems to just be mixing types willy-nilly, and I just can't come up with an explanation as to why. If I add additional parameters to the initial call, it always burrows down to that last step before failing, so presumably the recursion itself is at least partially working. This is in direct contrast to the initial attempt, which always failed to find a function call right away.
Ultimately, I've gotten past the problem, with a fairly elegant solution that hardly resembles either of the first two attempts. So I know how to do what I want to do. I'm looking for an explanation for the failure I saw.
Full code to follow since I'm sure my verbal description was insufficient. First some boilerplate, if you feel compelled to execute the code and see it for yourself. Then the initial attempt, which failed reasonably, then the second attempt, which did not.
#include <iostream>
using std::cout;
using std::endl;
#include <utility>
template<typename T1, typename T2>
std::ostream& operator <<(std::ostream& str, const std::pair<T1, T2>& p) {
return str << "[" << p.first << ", " << p.second << "]";
}
//Insert code here
int main() {
Execute(5, 6, 4.3, 2.2, 'c', 'd');
Execute(5, 6, 4.3, 2.2);
Execute(5, 6);
return 0;
}
Non-struct solution:
template<typename Type>
Type BuildFunction(const Type& t0, const Type& t1) {
return t0 + t1;
}
template<typename Type, typename... Rest>
auto BuildFunction(const Type& t0, const Type& t1, const Rest&... rest)
-> std::pair<Type, decltype(BuildFunction(rest...))> {
return std::pair<Type, decltype(BuildFunction(rest...))>
(t0 + t1, BuildFunction(rest...));
}
template<typename... Types>
void Execute(const Types&... t) {
cout << BuildFunction(t...) << endl;
}
Resulting errors:
test.cpp: In function 'void Execute(const Types& ...) [with Types = {int, int, double, double, char, char}]':
test.cpp:33:35: instantiated from here
test.cpp:28:3: error: no matching function for call to 'BuildFunction(const int&, const int&, const double&, const double&, const char&, const char&)'
Struct solution:
template<typename... Types>
struct BuildStruct;
template<typename Type>
struct BuildStruct<Type, Type> {
static Type Go(const Type& t0, const Type& t1) { return t0 + t1; }
};
template<typename Type, typename... Types>
struct BuildStruct<Type, Type, Types...> {
static auto Go(const Type& t0, const Type& t1, const Types&... rest)
-> std::pair<Type, decltype(BuildStruct<Types...>::Go(rest...))> {
return std::pair<Type, decltype(BuildStruct<Types...>::Go(rest...))>
(t0 + t1, BuildStruct<Types...>::Go(rest...));
}
};
template<typename... Types>
void Execute(const Types&... t) {
cout << BuildStruct<Types...>::Go(t...) << endl;
}
Resulting errors:
test.cpp: In instantiation of 'BuildStruct<int, int, double, double, char, char>':
test.cpp:33:3: instantiated from 'void Execute(const Types& ...) [with Types = {int, int, double, double, char, char}]'
test.cpp:38:41: instantiated from here
test.cpp:24:15: error: no matching function for call to 'BuildStruct<double, double, char, char>::Go(const char&, const char&)'
test.cpp:24:15: note: candidate is: static std::pair<Type, decltype (BuildStruct<Types ...>::Go(BuildStruct<Type, Type, Types ...>::Go::rest ...))> BuildStruct<Type, Type, Types ...>::Go(const Type&, const Type&, const Types& ...) [with Type = double, Types = {char, char}, decltype (BuildStruct<Types ...>::Go(BuildStruct<Type, Type, Types ...>::Go::rest ...)) = char]
test.cpp: In function 'void Execute(const Types& ...) [with Types = {int, int, double, double, char, char}]':
test.cpp:38:41: instantiated from here
test.cpp:33:3: error: 'Go' is not a member of 'BuildStruct<int, int, double, double, char, char>'
Reading the comments, it seems clear enough that this is a very localized bug in a particular version of G++, and that's all the answer there will ever be.