How to prevent std::function
to bool
conversion in C function overloading?
such as
class Object final {
public:
Object(bool boolean) : type_(22) {} //#1
Object(const std::function<int(int*, int)> value) : type_(11) {} //#2
int rettype() { return type_; };
private:
int type_;
};
int Println(int *args, int nargs) {
printf("Println\n");
return 0;
}
int main() {
cout << Object(Println).rettype() << endl; // 22
cout << Object(std::function<int(int*, int)>(Println)).rettype() << endl; // 11
}
I want to call #2 through Object(Println)
instead of Object(std::function<int(int*, int)>(Println))
,but the result is that #1 is called
How should I achieve this?
CodePudding user response:
The modern C solution here would be
Object::Object(std::invocable<int*, int> auto f)
You don't care exactly what the type of f is - that's clear from the fact that you consider std::function<int(int*, int)>
and int(*)(int*, int)>
interchangeable. std::invocable
is slightly more general than that: it says anything callable is also OK. A lambda would also work.
CodePudding user response:
How about adding a function pointer constructor?
Object(int (*value)(int*, int)) : Object(std::function<int(int*, int)>(value)) {}
You can also alias the function type:
using FunctionType = int (*)(int*, int);
Object(FunctionType value) : Object(std::function<int(int*, int)>(value)) {}
CodePudding user response:
Why not a templated constructor which requires that the passed type is convertible to the desired function type?
template<typename F,
typename std::enable_if<std::is_convertible<F, std::function<int(int*, int)>>::value, bool>::type = true>
Object(const F&) : type_(11) {}
The advantage is that you don't even have to truly have any std::function
object at run time. You simply check at compile time that it could be converted to it, but then you use the callable as it is, being it a function pointer, a lambda, or whatever.
CodePudding user response:
Check compiler warnings
warning: the address of 'int Println(int*, int)' will never be NULL [-Waddress]
It means that function pointer automatically auto converting the boolean
integral type.
To prevent this you can handle function pointer type by additional type deduction specifier. std::function is a functional object e.g. functor, not a raw C function pointer and simply have a converting constructor
For example:
For example:
#include <iostream>
#include <functional>
class Object final {
public:
explicit Object(bool boolean) : type_(22) {} //#1
explicit Object(int(*)(int*,int)) : type_(11) {}
explicit Object(const std::function<int(int*, int)>& value) : type_(11) {} //#2
int rettype() { return type_; };
private:
int type_;
};
int Println(int *args, int nargs)
{
std::cout << "Println" << std::endl;
return 0;
}
struct PrintLine
{
int operator()(int*, int)
{
std::cout << "PrintLine" << std::endl;
return 0;
}
};
int main(int argc, const char** argv)
{
std::cout << Object(Println).rettype() << std::endl; // 11
PrintLine pl;
std::cout << Object(pl).rettype() << std::endl; // 11
std::cout << Object(1).rettype() << std::endl; // 22
return 0;
}
CodePudding user response:
You can use only one constructor, but template and select what you want to do inside
template<class T>
Object(T t) {
if( std::is_same_v<T,bool>::value )
{
type_ = 22;
}
else
{
type_ = 11;
}
}
demo 17 : https://wandbox.org/permlink/0eMXkH1l8HzbdfC0
demo 11 : https://wandbox.org/permlink/rOP4JRAP2Ywb1osf
demo 11 in member initializer list : https://wandbox.org/permlink/6QDD4Vdo9TaqU4fT
It's only a POC, you may want check if the type is a type you want and fail if it's not what you expect.