I'm getting the following error
min.cpp:17:30: error: no viable conversion from '<overloaded function type>' to 'Container::UnaryFun' (aka 'function<double (double)>')
this->addFunction("abs", abs);
when trying to compile the following code:
#include <cmath>
#include <string>
#include <functional>
class Test
{
public:
using UnaryFun = std::function<double (double)>;
Test()
{
this->addFunction("abs", abs);
}
auto addFunction(const std::string& name, UnaryFun fun) -> void
{
// ...
}
};
auto main() -> int {
Test eval;
return 0;
}
I've tried to check the declaration of std::abs for argument double and return type double and looks like this:
inline _LIBCPP_INLINE_VISIBILITY double abs(double __lcpp_x) _NOEXCEPT {
return __builtin_fabs(__lcpp_x);
}
in /usr/local/Cellar/llvm/15.0.7_1/include/c++/v1/stdlib.h.
It is accesible specifically for the double type. I've checked this by adding:
double a = 5;
double b = std::abs(a);
and this compiles without problems or conversion warnings.
I've tried to declare my own abs function like so:
inline double xabs(double val)
{
return val < 0 ? -val : val;
}
and then change the following code like so to use this new xabs instead of std::abs
this->addFunction("abs", xabs);
and after this change, the code compiles.
Any ideas why the code with std::abs doesn't compile?
My environment:
OS: Mac OS 12.6
Compiler:
Apple clang version 14.0.0 (clang-1400.0.29.202)
Target: x86_64-apple-darwin21.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
Command to compile: g++ -std=c++2a -o min min.cpp
Update based on comments
I dug a bit deeper, and it seems that there is a problem with how std::function is declared, which led to the problem above.
If I declare addFunction like so, without std::function, the problem disappears.
auto addFunction(const std::string& name, double (*fun)(double)) -> void
{
}
This means that the compiler cannot figure out the matching abs if std::function is used but it can identify the matching overload if the type of the function is described directly without std::function.
The problem is that, since it has multiple overloads, std::abs doesn't have a single type. That means that the compiler can't select a std::function constructor to use to convert it since it can't deduce a type for the constructor's template parameter.
There are a couple of ways to get around that:
Use a cast:
addFunction("abs", std::static_cast<double(*)(double)>(std::abs));
Wrap it in a lambda:
addFunction("abs", [](double d) { return std::abs(d); });
As you've done, wrap it in a non-overloaded function
Related
I want to set the array length to be the minimum of a constant and a generic like this:
template <int foo> struct Bar{
void my_func( int const (&my_array)[std::min(5, foo)] ) { /*...*/ }
};
This code compiles with clang++ but not g++ and I need my code to work with both. The error g++ gives is: error: array bound is not an integer constant before ']' token. How I can set the length of this array to be the minimum of foo and 5?
When I use clang++ I run into the problem that I can't get anything to bind to my_array. I want to run something like:
int main() {
static const int var[5] = {0,1,2,3,4};
Bar<5> bar;
bar.my_func(var);
}
But when I try to compile this code in clang++ I get: error: reference to type 'const int [*]' could not bind to an lvalue of type 'const int [5]'.
If I get rid of the std::min() stuff and replace it with foo the code compiles and runs fine.
Notes:
To get this code to compile you'll need to #include <algorithm> or similar to access std::min.
I don't think that this being part of a template should matter but when I try similar things with non-template function such as:
const int const_five = 5;
void new_func( int const (&my_array)[std::min(5,const_five)] ) { /*...*/ }
g++ says: error: variable or field 'new_func' declared void and clang++ says candidate function not viable: no known conversion from 'const int [5]' to 'const int [std::min(5, const_five)]' for 1st argument which both look like similar problems.
For int const (&my_array)[std::min(5, foo)] to compile, you need a version of std::min which is constexpr. It is since C++14.
Check the default value for -std of gcc and clang you use (its version-dependant). Ultimately, compile with -std=c++14.
Provided by StoryTeller, a nice working MCVE.
Keep it simple:
[foo < 5 ? foo : 5]
I have the following code
#include <boost/function.hpp>
#include <boost/bind.hpp>
class Foo {
public:
int getIfoo();
};
int Foo::getIfoo() {
return 5;
}
int main () {
boost::function<int (Foo)> getIntFoo;
getIntFoo = boost::bind( &Foo::getIfoo, _1 );
return 0;
}
When I compile with the following command g++ TestBoostBind.cpp I've got the following error
/includes/boost_1_60_0/boost/bind/mem_fn_template.hpp:35:36: error: invalid conversion from ‘const Foo*’ to ‘Foo*’ [-fpermissive]
BOOST_MEM_FN_RETURN (u.*f_)();
~~~~~~~^~
I'm confused about the source of the error whether it's originally from my code or the boost library. Does anyone know what the error means and how to fix it? I use g++ (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0 and boost.1.60
When binding to a member function, the first argument needs to be a pointer or a reference to the object to call the function on. It specifically can't be a value (an actual object instance). The boost::bind function have special cases for these two alternatives to generate the correct objects. It does not have any special case for passing by value.
Therefore you need to define getIntFoo as a function taking a pointer to Foo:
boost::function<int (Foo*)> getIntFoo;
Or a reference:
boost::function<int (Foo&)> getIntFoo;
You could try to use std::mem_fn to achieve the same goal:
Foo f;
std::function<int(Foo &)> getIntFoo = std::mem_fn(&Foo::getIfoo);
int ret = getIntFoo(f);
or if you need pointer argument, std::function could resolve this for you:
Foo f;
std::function<int(Foo *)> getIntFoo = std::mem_fn(&Foo::getIfoo);
int ret = getIntFoo(&f);
boost have its own alternative
This question already has an answer here:
Pass anonymous function object to std::function?
(1 answer)
Closed 7 years ago.
What I am trying to achieve is to make a functor that can take different functors as arguments.
Edit: the reason for my problem, the "most vexing parse", and the solution are well-described: see this question and answer, the whole most-vexing-parse tag, and even the wikipedia page. Still, I was not able to identify the problem before asking, and will leave this question as it might help others.
What I did:
In a header file functor.hpp:
#ifndef FUNCTOR_HPP
#define FUNCTOR_HPP
#include <functional>
template <typename T, typename BinOp = typename std::plus<T>>
struct doer {
BinOp op;
doer(BinOp o = std::plus<T>()) : op(o) {}
T operator()(const T& a, const T& b) const
{ return op(a, b); }
};
#endif // FUNCTOR_HPP
With this header, I can write a program functor.cpp like this:
#include <iostream>
#include "functor.hpp"
int main()
{
doer<int> f;
std::cout << f(3, 7) << std::endl;
}
and I can compile and run it to get, as expected:
$ make functor
g++ -std=c++14 -pedantic -Wall functor.cpp -o functor
$ ./functor
10
$
I am struggling to find a way to instantiate my doer with a different operator (not std::plus<T>).
doer<int, std::multiplies<int>> f2(std::multiplies<int>());
This compiles without a problem, but I have not been able to figure out a way to call f2(3, 7), to get the product 21. For example, if I add another line to the program:
int r = f2(3, 7);
and try to compile, I get:
$ make functor
g++ -std=c++14 -pedantic -Wall functor.cpp -o functor
functor.cpp: In function ‘int main()’:
functor.cpp:10:20: error: invalid conversion from ‘int’ to ‘std::multiplies<int> (*)()’ [-fpermissive]
int r = f2(3, 7);
^
functor.cpp:10:20: error: too many arguments to function ‘doer<int, std::multiplies<int> > f2(std::multiplies<int> (*)())’
functor.cpp:9:37: note: declared here
doer<int, std::multiplies<int>> f2(std::multiplies<int>());
^
functor.cpp:10:20: error: cannot convert ‘doer<int, std::multiplies<int> >’ to ‘int’ in initialization
int r = f2(3, 7);
^
What is going on? Seems almost like f2(3, 7) somehow is not calling the overloaded operator()...
Most vexing parse. Try this:
doer<int, std::multiplies<int>> f2((std::multiplies<int>()));
or this:
doer<int, std::multiplies<int>> f2 = std::multiplies<int>();
or this:
doer<int, std::multiplies<int>> f2{std::multiplies<int>()};
Take the following code, which is characterized by
Reliance on ADL for a specific behavior (volume)
Using decltype for return type and relying on SFINAE to discard extra overloads
namespace Nature {
struct Plant {};
double volume(Plant){ return 3.14; }
}
namespace Industrial {
struct Plant {};
double volume(Plant) { return 100; }
}
namespace SoundEffects {
// A workaround for GCC, but why?
////template<class T> void volume();
template<class aSound>
auto mix(aSound& s) -> decltype(volume(s)*0.1)
{
return volume(s)*.1;
}
struct Samples {
Nature::Plant np;
Industrial::Plant ip;
};
inline double mix(const Samples& s) {
return mix(s.np) + mix(s.ip);
}
}
int main()
{
SoundEffects::Samples s;
assert( mix(s) == 100*.1 + 3.14*.1 );
}
The code as presented (without the template<class T> void volume() line), VS 2012 and clang 3.5 compiles successfully, and runtime is as expected. However, GCC 4.7.2 says:
template-function-overload.cpp: In substitution of 'template<class aSound> decltype ((volume(s) * 1.0000000000000001e-1)) SoundEffects::mix(aSound&) [with aSound = SoundEffects::Samples]':
template-function-overload.cpp:46:4: required from here
template-function-overload.cpp:23:9: error: 'volume' was not declared in this scope
template-function-overload.cpp:23:9: note: suggested alternatives:
template-function-overload.cpp:9:11: note: 'Nature::volume'
template-function-overload.cpp:14:11: note: 'Industrial::volume'
With the extra template volume line, all three compile and run fine.
So, there is clearly a compiler defect here. My question is, which compiler is the defective one? And which C++ standard is being violated?
This was a bug which was fixed since GCC 4.8. Here's a simplified version of the code that gives the same error:
template<class T>
auto buzz(T x) -> decltype(foo(x));
void buzz(int);
int main() {
buzz(5); // error: 'foo' was not declared in this scope
}
In mix(s), both overloads of SoundEffects::mix are compiled into the set of candidate overloads via ADL (SoundEffects is an associated namespace of SoundEffects::Sample). The function template overload is evaluated for viability. The error occurs because volume(s) cannot be resolved to a suitable overload either via pure unqualified lookup or ADL for Sample.
The reason this should pass is that when lookup fails a substitution failure should occur (since volume(s) is dependent) and the template should be rejected from overload resolution. This would leave mix(const Sample&) as the only viable overload to select. The fact that there is a hard error is clearly a sign that this GCC version has a faulty SFINAE implementation.
Consider the following code, which uses a function with variable arguments:
#include <iostream>
// Typedef function type
template<typename... Output>
using Func = void(Output*...);
// Function runner
template<typename... Output>
void run_func(Func<Output...>& func, Output*... output) {
for (int i=0 ; i < 10 ; ++i) {
func(output...);
}
}
void f(double* d) {
*d *= 2;
};
int main() {
double value = 1.0;
run_func(f, &value);
printf("%f\n", value);
}
Compiling this with g++ 4.7.3 works fine, and running produces 1024.0 as expected.
Compiling using icpc 14.0.2 crashes it...
templ.cc(21): internal error: assertion failed: lower_expr: bad kind (shared/cfe/edgcpfe/lower_il.c, line 18582)
run_func(f, &value);
^
Compiling with clang 3.5.0-1 gives the following error message:
templ.cc:21:3: error: no matching function for call to 'run_func'
run_func(f, &value);
^~~~~~~~
templ.cc:9:6: note: candidate template ignored: deduced conflicting types for parameter 'Output' ('double' vs. <double>)
void run_func(Func<Output...>& func, Output*... output) {
^
Is this a bug, or should have g++ not compiled this?
Why is clang deducing these "conflicting" types of double and <double>, is <double> meant to represent an unpacked arglist for example?
Update icpc 14.0.3 does not crash, and the program compiles and runs correctly.
See DPD200244439 at Intel® Composer XE 2013 SP1 Compilers Fixes List
Following the above discussion, it seems that this is indeed a bug in clang.
As pointed out by gha.st, skipping template using and using the native function type directly works:
void run_func(void (&func)(Output*...), Output*... output) {
I have a filed a bug against this here.