Implicit argument conversion ambiguity in non-member functions overloads with std::function? - c++

Editted - please skip to the edit, which has the real problem
I frequently run into situations in my string helper library of stand-alone functions, where I provide overloads of a function with versions that take a char and versions that take a std::string.
The problem is, the overload then becomes ambiguous when passed a string literal (const char*).
Example:
void myFunc(const std::string &subStr);
void myFunc(char character);
These two functions are implemented differently, one optimized for strings and one for a single char.
Howsoever, trying to call myFunc("literal") results in ambiguity, despite me always wanting it to call the std::string version.
This forces me to provide void myFunc(const char *str) versions of my overloads, which only are stubs like:
void myFunc(const char *str)
{
myFunc(std::string(str));
}
Is there some way to make these stub functions unnecessary? I'd like to just be able to make void myFunc(char c) 'explicit', but you can't make non-constructor non-member functions explicit. Which would solve the problem instantly. =(...
(As an aside, why can't you make standalone functions explicit?)
Edit:
You know what they say about programmers coding too late into the night! (If you remember the joke, tell me, because I was too sleepy when I originally heard it and I've since forgotten it)
The real problem
I'm using MinGW v4.7.2, and the problem was alot different then my post originally assumed.
The problem is, I have several overloads. Yes, this example works fine:
void myFunc(const std::string &subStr);
void myFunc(char character);
But if you add an std::function overload, it breaks down:
void myFunc(const std::string &subStr);
//Not actually part of the problem; I was confused by part of the error message highlighting this function.
//void myFunc(char character);
void myFunc(std::function<bool(char)); //<-- The real problem
My string library has std::string, char, and std::function overloads (and occasionally a few more overloads for simplifying functions with alot of optional parameters).
When I have std::function as an overload, I get this error message:
error: call of overloaded ‘myFunc(const char [15])’ is ambiguous
candidates are:
void myFunc(char) <near match>
no known conversion for argument 1 from ‘const char [15]’ to ‘char’
void myFunc(std::function<bool(char)>)
void myFunc(const string&)
The myFunc(char) was how I initially got confused last night. Removing that overload from the code, I get the error message:
error: call of overloaded ‘myFunc(const char [15])’ is ambiguous
candidates are:
void myFunc(std::function<bool(char)>)
void myFunc(const string&)
Here's a self-contained compilable example.
How can I make a string literal choose the std::string over the std::function?
It's probably ambiguous because std::function's constructor is templated and is designed to take a function pointer, among other things.
Since my string library, specifically, uses only std::function<bool(char)> and std::function<bool(const std::string&)>, already typedef'd, I could inherit those into a class with an explicit constructor.
Is there other suggestions or options available?

Can you update your compiler? Your example compiles as expected in g++4.8 and above.
This is actually is a current defect report in the C++ standard. See 2132. std::function ambiguity. It is currently in review status, but most likely will be accepted. This will make sure that non-Callable types like your example never participate in overload resolution:
These constructors shall not participate in overload resolution unless
f is Callable
Currently g++4.8 and above implements this.

You did not provide self-contained repro so it's hard to say what's wrong.
But here are a couple of guesses:
You have a bug in compiler (unlikely)
You don't call character overload properly. You should call it like that: myFunc('c').
You provided incorrect calling code or incorrect method signature(s).
I guess following code snippet should explain what should be happening and how to declare and call methods properly. Note myOtherFunc trick with capturing literal. It can be done better w/o template function, with smart wrapper around string, but I'll leave that out.
You can also try it on your compiler and see if it works, then we'll know if you have compiler problem.
Live code: http://codepad.org/gzB7xWs2
#include <string>
#include <iostream>
using namespace std;
void myFunc(char c) {
cout << "myFunc called with char" << endl;
}
void myFunc(const string& s) {
cout << "myFunc called with string" << endl;
}
void myOtherFunc(char c) {
cout << "myOtherFunc called with char" << endl;
}
void myOtherFunc(const string& s) {
cout << "myOtherFunc called with string" << endl;
}
template <size_t StingSizeWithNullTerminator>
void myOtherFunc(const char (&buf)[StingSizeWithNullTerminator]){
cout << "myOtherFunc called with literal of size " << (StingSizeWithNullTerminator - 1) << endl;
}
int main() {
myFunc("string");
myFunc('c');
myFunc(string("std string"));
myOtherFunc("string");
myOtherFunc('c');
myOtherFunc(string("string"));
return 0;
}
Output:
myFunc called with string
myFunc called with char
myFunc called with string
myOtherFunc called with literal of size 6
myOtherFunc called with char
myOtherFunc called with string
Update
Now, with the example, it's clear what the problem is.
The problem is that there is no method with exact signature that accepts char[15]. And compiler needs to perform conversion.
The problem is that it can either convert to std::string or to std::function (because std::function has template constructor which accepts any type, including char[15]). Therefore it can't choose which conversion to use and gives up.
Therefore there's no clean solution for that as far as I know of, but here are some no-so-clean:
Use explicit conversion to std::string when calling methods
Ask yourself (and maybe tell us), what's the reason for having myFunc which accepts both strings and functions. Maybe there's a problem with design and you can avoid having functions with same names.
If you only need to accept bool(&)(char) function, you can use custom wrapper instead (see example below)
Example for 3rd option (http://ideone.com/o0NqUf):
#include <iostream>
#include <functional> //Required for std::function.
struct Callback
{
Callback(bool (&func)(char)): m_func(func)
{}
bool operator()(char c) { return m_func(c); }
bool (&m_func)(char);
};
void myFunc(Callback seperatorFunc)
{
std::cout << "Callback overload" << std::endl;
}
void myFunc(const std::string &separator)
{
std::cout << "std::string overload" << std::endl;
}
bool testCallback(char)
{
return true;
}
int main()
{
myFunc("String literal");
myFunc(std::string("std::string"));
myFunc(testCallback);
return 0;
}
Output:
std::string overload
std::string overload
Callback overload

You should be able to SFINAE yourself very easily out of this one:
template <typename F>
auto myFunc(F f) -> decltype(!f('0'), std::function<bool(char)>(f), void()) {
std::cout << "std::function<bool(char)> overload" << std::endl;
}
Or, using a C++03 compiler (possibly using tr2/type_traits or Boost Type Traits if your compiler doesn't yet have them):
template <typename F>
void myFunc(F f, typename std::enable_if<std::is_constructible<
std::function<bool(char)>, F>::value>::type* = nullptr)
{
std::cout << "std::function<bool(char)> overload" << std::endl;
}
Proof it works:http://ideone.com/Q87JsV
#include <iostream>
#include <type_traits>
#include <functional>
#if 1
template <typename F>
auto myFunc(F f) -> decltype(!f('0'), std::function<bool(char)>(f), void()) {
std::cout << "std::function<bool(char)> overload" << std::endl;
}
#else
template <typename F>
void myFunc(F f, typename std::enable_if<std::is_constructible<
std::function<bool(char)>, F>::value>::type* = nullptr)
{
std::cout << "std::function<bool(char)> overload" << std::endl;
}
#endif
void myFunc(const std::string &seperator) {
std::cout << "std::string overload" << std::endl;
}
bool testCallback(char) {
return true;
}
int main()
{
myFunc("String literal");
myFunc(std::string("std::string"));
myFunc(testCallback);
}
Output:
std::string overload
std::string overload
std::function<bool(char)> overload

Related

Compile-time detection of missing user-defined to_string()

I want to provide a to_string(obj) function for every object type I create.
I found this question, applied the accepted answer, and it works. So far so good.
Then I created a new type, but forgot to write a to_string() for it (or better: I accidentally made it unreachable by ADL). The problem is: my program still compiles fine, and at runtime I get an obscure stack overflow(TM).
Is there a way to obtain a reasonable error message, instead?
Here is a small program to demonstrate the problem: an infinite recursion between notstd::to_string() and notstd::adl_helper::as_string().
#include <iostream>
#include <string>
namespace notstd {
namespace adl_helper {
using std::to_string;
template<class T>
std::string as_string( T&& t ) {
return to_string( std::forward<T>(t) );
}
}
template<class T>
std::string to_string( T&& t ) {
std::cout << "called" << std::endl; // <-- this is to show what's going on
return adl_helper::as_string(std::forward<T>(t));
}
class A {
/* both versions are needed, or the perfect forwarding candidate will
* always be chosen by the compiler in case of a non-perfect match */
//friend std::string to_string(A &a) { return std::string("a"); }
//friend std::string to_string(const A &a) { return std::string("a"); }
};
}
int main(int argc, char** argv) {
notstd::A a;
std::cout << to_string(a) << std::endl;
}
I tried creating a wrapper function that accepts one more parameter, to be used to perform the an anti-recursion check, like this:
#include <iostream>
#include <string>
#include <cassert>
namespace notstd {
namespace wrap_std {
std::string to_string(double v, bool) { return std::to_string(v); }
/* .... etc..... */
}
namespace adl_helper {
using wrap_std::to_string;
template<class T>
std::string as_string( T&& t ) {
return to_string( std::forward<T>(t), true );
}
}
template<class T>
std::string to_string( T&& t, bool recurring = false ) {
std::cout << "called" << std::endl;
assert(!recurring);
return adl_helper::as_string(std::forward<T>(t));
}
class A {
/* both versions are needed, or the perfect forwarding candidate will
* always be chosen by the compiler in case of a non-perfect match */
//friend std::string to_string(A &a) { return std::string("A"); }
//friend std::string to_string(const A &a) { return std::string("A"); }
};
}
int main(int argc, char** argv) {
notstd::A a;
std::cout << to_string(a) << std::endl;
}
The problems here are:
I'd have to wrap all std::to_string() overloads
I'll only get a runtime error, but I feel the problem could and should be detected ad compile time
I'm probably adding some overhead, for something useful only during development: maybe I could add some macros to deactivate all this in release mode, but it would add even more work
Maybe I could use a template to wrap std::to_string() and create specializations for my types... this would be a quite different beast, but at least it would provide a compile time error if a suitable specialization is not available. I would have, again, to wrap all std::to_string() overloads, and I'd probably have to (almost) forget about ADL, at least until c++20 is supported by all compilers, If I understand well.
Does anyone have a better solution?
Thanks!
The idea of that accepted answer is different: you put A outside notstd namespace and then use qualified notstd::to_string instead of unqualified to_string. That is:
namespace notstd {
// ...
}
class A {
friend std::string to_string(const A&);
};
A a;
std::cout << notstd::to_string(a);
Now your code won't compile if there is no friend function. Moreover, you need only one friend function (taking const A&), because notstd::to_string(T&&) won't be present in the overload set inside adl_helper::as_string(T&&).
Putting A inside notstd screws everything up. You have infinite recursion problem and you need two friends to handle both A and const A cases in the presence of notstd::to_string(T&&) candidate: if only one friend is defined, that candidate is a better match in one of the cases because const qualifier should be added/dropped to invoke the friend function.

"Transforming" Function Arguments

I'm writing C++ class that interfaces with a library. The library has a bunch of functions that look like the following:
Library.h
int FunctionA(int deviceNumber, ...);
int FunctionB(int deviceNumber, ...);
int FunctionC(int deviceNumber, ...);
int FunctionD(int deviceNumber, ...);
int FunctionE(int deviceNumber, ...);
Each instance of my C++ class has an associated deviceNumber which never changes, so I have deviceNumber stored as a member variable, and every time I call a library function, I pass the member in as the function call's first argument.
This is fine, and there's no real reason for me to change the way it is. But out of curiosity, I was wondering if C++ had any mechanism to "transform" arguments that would let me avoid passing the same argument in every call. The obvious way to accomplish this is to overload everything. Let's say my class is called Foo:
Foo.cpp
int Foo::FunctionA(...) {
// deviceNumber_ is a const member
return ::FunctionA(deviceNumber_, ...);
}
The only problem is that this requires a method for each function call, so as the library grows, it gets more and more annoying without a code generator.
Is there any general way to provide the overloading behaviour without actually overloading the functions? Is there a mechanism in C++ to "expand" an argument into multiple arguments? I'm imagining it would look like:
// These two calls are equivalent
FunctionA(deviceNumber, ...);
FunctionA(Magic(...));
// Magic() expands the arguments, adding deviceNumber
Even if the solution is much uglier and less readable than leaving everything alone, I'm curious if it's possible. After searching around, variadic templates seem to be the closest match, but I can't really wrap my head around how they could be used to accomplish this.
You might be happy with a generic relay function:
Live On Coliru
#include <iostream>
int foo1(int device_number, const char*) { std::cout << __PRETTY_FUNCTION__ << "\n"; return device_number*42; }
double foo2(int device_number) { std::cout << __PRETTY_FUNCTION__ << "\n"; return device_number*3.14159; }
struct facade {
facade(int dn) : device_number(dn) {}
template <typename F, typename... A>
auto call(F&& f, A&&... args) const {
return std::forward<F>(f)(device_number, std::forward<A>(args)...);
}
private:
int device_number;
};
int main() {
facade dev(2);
std::cout << dev.call(foo1, "yes ma'am") << "\n";
std::cout << dev.call(foo2) << "\n";
}
I would probably choose a marco in the cpp file as the easiest solution (strictly in the cpp file though)
Variadic templates could help here too. However it sounds like you are doing something embedded and that might be an issue.
Also, I'm not sure if you mean that each FunctionA is overloaded or FunctionA refers to exactly one function.
Anyway, my template solution will help if there are multiple FunctionAs
template<typename... Args>
int Foo::FunctionA(Args&& ...args) {
return ::FunctionA(deviceNumber_, std::forward<Args>(args)...);
}
I put pseudo code , for C++ type structure.
Class Prototype might be following forms.
class Foo {
private private_member_of_deviceNumber;
....
int FunctionA(...);
....
}
Foo Class constructor will assign deviceNumber to private member variable.
class Foo::Foo(int deviceNumber) {
int private_member_of_deviceNumber = deviceNumber;
}
Foo Class member FunctionA(...) will like this form.
int Foo::FunctionA(...) {
return ::FunctionA( private_member_of_deviceNumber , ...);
}
How about like this way?

How to create a method to which I could either pass function or a functor?

Basically, I am implementing a container class. I need to create a method which sorts the data according to the comparator function/functor which must be passed with the sort request. Since declaration and definition of the method are in different files(.h and .cpp) using templates becomes a problem (and I don't have much experience using them). In other words, I want to make a method:
void sort(function/functor f);
and I don't know how to define the function. So, is there any solution to this problem?
If you know the signature of the function/functor to be passed[*], you can use std::function. Or boost::function if you don't have C++11. So for a comparator it would be:
void sort(std::function<bool(const Element&, const Element&)> f);
where Element is the type of the elements of the container.
Failing that you could define a class with a virtual compare function, and allow callers to derive from it with their own class. It's more work for callers, but that's exactly what std::function provides: a way for callers to not have to do that.
Two warnings:
make sure there's really a good reason for the implementation of your container not to be in the header file. All of the standard containers are implemented in header files, and that mostly works OK.
make sure there's really a good reason for you to implement a sort function. Standard containers only have sort functions where std::sort doesn't work: std::list and std::forward_list.
[*] Actually std::function doesn't require the exact same signature. You just say the types you want to call it with and the type you want to convert the return value to. So if you call it with two ints and the caller provides a function that takes two longs, then that's fine. The arguments are converted just like the function call would without any std::function.
This is generally done with templates. Like this:
#include <iostream> // For example output only.
template <typename F>
void sort(F&& pred) {
pred(123);
}
void normal_func(int v) {
std::cout << "normal_func(" << v << ")\n";
}
struct my_pred {
void operator()(int v) const {
std::cout << "my_pred(" << v << ")\n";
}
};
int main() {
sort([](int v) { std::cout << "Called lambda func with " << v << '\n'; });
sort(normal_func);
sort(my_pred());
}
If, however, templates cannot be used, then your best bet would be to use polymorphic function wrapper like std::function (or boost::function, or you can write your own simple version).
Alternatively, you can use a hardcore C-style regular function along with a void pointer where user can save their context. For example, like qsort(). Though I'd try not to go there if possible.
Here is an example using std::function:
#include <iostream> // For example output only.
#include <functional> // For std::function.
void sort(const std::function<void(int)>& pred) {
pred(123);
}
void normal_func(int v) {
std::cout << "normal_func(" << v << ")\n";
}
struct my_pred {
void operator()(int v) const {
std::cout << "my_pred(" << v << ")\n";
}
};
int main() {
sort([](int v) { std::cout << "Called lambda func with " << v << '\n'; });
sort(normal_func);
sort(my_pred());
}
Hope it helps.
You can use std::function as suggested in Steve Jessop's answer but in this case I think you should consider making your sort function a template function as in Vlad's answer. A sort function has to call the comparator many times and there will be noticeable overhead to using std::function in this situation.
The easiest solution is to use a template:
class C
{
template<typename T>
void sort(T func)
{
func(12,45); // Will compile as long as your function/functor
} // Can take two integers as parameters.
}; // NOTE: or integers can be converted into your parameters.
If you want to specify using old C notation.
typedef void (*FUNC_TYPE)(int, int); // declares a function pointer type.
// returns void takes two integers.
class C
{
void sort(FUNC_TYPE func)
{
func(12,45); // Compiles only if the function
} // matches the exact type.
};
The C++11 way
class C
{
void sort(std::function<void(int,int)> func)
{
func(12,45); // Will match any func/functor that
// will return a void and takes two
} // integers.
};

Create Functions that takes variable amount of parameters and data types

I know this question might be a little weird but the creators of C++ made it so that whenever we create a function in C++ we can specify what we want our parameters to be for example we can create a function like this:
void function(int test);
As well as we can create a function like this:
void function(std::string test);
How do I re-create that effect? I'm in the midst of creating a delegate class that works somewhat like CA# delegates but I'm having a problem when it comes to the parameters. I don't know what type of variable they'll want to store in the delegate so I have to implement something that they can specify which variable types they'll be using. Something like this:
Delegate myDelegate(std::string, int, float);
Is it possible to do that? I've looked into variadic functions but you have to know which type to cast it too. I know I could have indicators like "%d and %s" just like the printf function but is there a way to implement it so that it accepts the object names rather than a indicator? I hope this is simple to understand.
You can use variadic argument lists. Here is a quick example:
#include <algorithm>
#include <iostream>
#include <vector>
#include <functional>
template <typename... T>
class Delegate {
std::vector<std::function<void(T...)>> d_delegates;
public:
template <typename F>
void add(F&& f) { this->d_delegates.push_back(std::forward<F>(f)); }
template <typename... S>
void operator()(S... args) const {
std::for_each(this->d_delegates.begin(), this->d_delegates.end(),
[&](std::function<void(T...)> const& f){ f(args...); });
}
};
void f1(int i) { std::cout << "f1(" << i << ")\n"; }
void f2(int i, double d) { std::cout << "f2(" << i << ", " << d << ")\n"; }
int main() {
Delegate<int> d1;
d1.add(f1);
d1(17);
Delegate<int, double> d2;
d2.add(f2);
d2(42, 3.14);
}
A simple solution would just be function overloading. Also, if future code maintenance is required, it would provide the most clarity (at least that is my hunch). Anyway, this would produce exactly the behavior you are describing.

A common type cast for lambda's and functions to reference later

Why is it the second example does not work? Is there a way I could get the second example to work while still type casting the lambda or function into a medium to reference later?
// Types I'm using
typedef void (*ANY_FUNC)(...);
typedef void (*VOID_FUNC)();
This works
void call_void( VOID_FUNC func) {
((ANY_FUNC)func)();
};
// ...
call_void([]() { /* do something */ });
This doesn't
template <typename fn>
void call_any( fn func ) {
((ANY_FUNC)func)();
};
// ...
call_any([]() { /* do something */ });
Please ignore the fact that you would never need to use the second example how it is now. It's only for demonstration (relative code).
Both examples work with function pointers instead of lambdas.
As long as you are declaring a template you can just use the incoming function object directly. Also, you should declare your function argument as a reference not as by value:
template <typename fn>
void call_any(fn&& func) {
func();
};
And if you want to call a function with arguments you can do:
template <typename fn, typename... Args>
void call_any_many(fn&& func, Args&&... args) {
func(std::forward<Args>(args)...);
};
Usage example:
int main ()
{
call_void([]() { std::cout << "Hello, void World!" << std::endl; });
call_any([]() { std::cout << "Hello, any World!" << std::endl; });
call_any_many([](int x) { std::cout << "Hello, any many World-" << x << "!" << std::endl; }, 1234);
return 0;
}
But if your intention is to store some function pointers and not to call them directly, I suggest using std::function from <functional> header. You can see some information and example from here: http://en.cppreference.com/w/cpp/utility/functional/function
For example:
#include <iostream>
#include <functional>
int main ()
{
std::function<void()> anyf = []() { std::cout << "Hello, any World!" << std::endl; };
std::function<void(int)> intf = [](int x) { std::cout << "Hello, any many World-" << x << "!" << std::endl; };
anyf();
intf(1234);
return 0;
}
I don't think any of them really works, except perhaps by chance on some compilers.
The difference with a lambda is that it is convertible to a function pointer, but it isn't one. The templated version will notice this difference, and fn is not deduced as VOID_FUNC.
Lambdas are implicitly convertible to function pointers (but only if they don't capture anything), so just change call_any's parameter to a function pointer:
void call_any(ANY_FUNC func)
{
(*func)();
}
You would need to call it with a lambda of the appropriate type:
call_any([](...) { /* ... */ });
But variable-length argument lists (aka varargs) are bad because they are as non-type-safe as you can get. Same with function pointers: they are non-object-oriented. You should think of an alternative mechanism, perhaps involving variadic templates and polymorphism (virtual methods)
The first is converting a lambda to a function pointer with corresponding argument and return types, then casting that to a vararg function, whereas the second is attempting to convert a lambda directly to a vararg function (i.e., a function without corresponding argument types).
The two conversions in the first example are allowed*, but the single conversion in the second is not.
* Note that the cast notation you use to convert between function pointer types ends up working like reinterpret_cast which states: "A function pointer can be explicitly converted to a function pointer of a different type. The effect of calling a function through a pointer to a function type (8.3.5) that is not the same as the type used in the definition of the function is undefined." And therefore the first example code has undefined behavior.