Consider this simple example code:
#include <functional>
#include <iostream>
void f(bool _switch) {
std::cout << "Nothing really" << std::endl;
}
void f(std::function<double (int)> _f) {
std::cout << "Nothing really, too" << std::endl;
}
int main ( int argc, char* argv[] ) {
f([](int _idx){ return 7.9;});
return 0;
}
It fails to compile:
$ g++ --std=c++11 main.cpp
main.cpp: In function ‘int main(int, char**)’:
main.cpp:15:33: error: call of overloaded ‘f(main(int, char**)::<lambda(int)>)’ is ambiguous
main.cpp:15:33: note: candidates are:
main.cpp:6:6: note: void f(bool)
main.cpp:10:6: note: void f(std::function<double(int)>)
However if I replace the second function with a reference argument it compiles fine. And again if it is replaced by a const reference it fails.
So I have some questions concerning this example:
Why is a lambda function implicitly convertible to bool in the first place?
Why does taking a std::function reference solve the ambiguity?
And most important to me, how can I avoid this problem? I need the second function to take either a (copy of a) std::function or a const reference to it.
A lambda function with no capture can be converted to a regular function pointer, which then has a standard conversion to a bool.
If you take the std::function by non-const reference, then that eliminates it as a candidate, since converting the lambda to a std::function requires a temporary, and a temporary cannot bind to a non-const reference. That just leaves f(bool) as a candidate, so there is no ambiguity.
There are many ways you could avoid the ambiguity. For example, you could create a std::function variable first:
std::function<double(int)> g = [](int _idx){ return 7.9;};
f(g);
or you could cast the lambda:
f(std::function<double(int)>([](int _idx){return 7.9;}));
You could have a helper function:
template<typename T>
std::function<T> make_function(T *f) { return {f}; }
int main ( int argc, char* argv[] ) {
f(make_function([](int _idx){ return 7.9;}));
return 0;
}
or you could grab the particular function you are interested in:
int main ( int argc, char* argv[] ) {
void (*f_func)(std::function<double(int)>) = f;
f_func([](int _idx){ return 7.9;});
return 0;
}
namespace details{
template<class Sig,class=void>
struct invoke {};
template<class F, class...Args>
struct invoke<F(Args...),decltype(void(
std::declval<F>()(std::declval<Args>()...)
))>{
using type=decltype(std::declval<F>()(std::declval<Args>()...));
};
}
template<class Sig>struct invoke:details::invoke<Sig>{};
template<typename Sig, typename T, typename=void>
struct invoke_test:std::false_type {};
template<typename R, typename...Args, typename T>
struct invoke_test<R(Args...), T,
typename std::enable_if<
std::is_convertible<
typename invoke<T(Args...)>::type,
R
>::value
>::type
>:std::true_type {};
template<typename...Args,typename T>
struct invoke_test<void(Args...),T,
decltype( void( typename invoke<T(Args...)>::type ) )
>:std::true_type{};
template<typename Sig, typename T>
constexpr bool invokable() {
return invoke_test<Sig,T>::value;
}
this gives us a pseudo-concept invokable.
We can then use it like:
template<typename F>
typename std::enable_if<invokable<double(int),F>()>::type
f(F&&){
std::cout << "can be invoked\n";
}
void f(bool) {
std::cout << "is bool\n";
}
and bob is your uncle.
The real problem is that std::function<double(int)> 's constructor does not do a similar test, and instead claims (falsely) that it can be constructed from anything at all. This is a flaw in the standard, one I suspect will be fixed once concepts are standardized.
You can get rid of the implicit conversion by creating a helper class
#include <functional>
#include <iostream>
struct Boolean {
bool state;
Boolean(bool b):state(b){}
operator bool(){ return state; }
};
void f(Boolean _switch) {
std::cout << "Nothing really " << _switch << std::endl;
}
void f(std::function<double (int)> _f) {
std::cout << "Nothing really, too" << std::endl;
}
int main ( int argc, char* argv[] ) {
f([](int _idx){ return 7.9;});
f(true);
return 0;
}
Should you ever want to call f with eg. a pointer and expect it to call the first overload you will have to cast it to either bool or add a corresponding constructor / cast to the helper class though.
One more option to Vaughn Cato's answer:
template<typename F>
void f(F _f) {
std::cout << "Nothing really, too: " << _f(3) << std::endl;
}
Now the second overload is a template, so it is chosen for a lambda (or anything), and the first is chosen for bool. So calling f is no more complex than needed.
But, one problem with that is if you want to add more overloads, and another is that the first overload will only be called if there is an exact match to bool.
Related
I'm getting tripped up on calling bind on an enable_if'd member function. I've worked around it using if constexpr, but I'm curious what the solution would be for this issue. The code is the simplest reproducer and not representative of the overarching problem I'm trying to solve. How can I make this work?
#include <iostream>
#include <type_traits>
#include <functional>
template <typename T>
class test {
public:
template <typename U = T>
typename std::enable_if<std::is_copy_constructible<U>::value, void>::type
foo(const T& v){
std::cout << "copy constructible";
}
template <typename U = T>
typename std::enable_if<!std::is_copy_constructible<U>::value, void>::type
foo(const T& v){
std::cout << "not copy constructible";
}
void foo_bar(const T& v){
std::cout << "test";
}
};
int main(int argn, char** argc){
test<int> myfoo;
myfoo.foo(3); //Works
auto func = std::bind(&test<int>::foo_bar, &myfoo, 3); //Works
auto func = std::bind(&test<int>::foo, &myfoo, 3); //Doesn't work
func();
return 0;
}
The problem is that U is substituted only when the member function template foo is actually called, and not when it is used inside of std::bind(). This means that when specifying &test<int>::foo inside bind(), it isn't known which of the two member function templates is going to be actually instantiated since the instantiation of definition will happen when we actually call foo(), and so the compiler can't decide which of them you're referring to. This is exactly what <unresolved overloaded function type> means in the error that you're getting:
no matching function for call to 'bind(<unresolved overloaded function type>, test<int>*, int)'
32 | auto func2 = std::bind(&test<int>::foo, &myfoo, 3); //Doesn't work
| ~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can solve this by either specifying U explicitly, like:
&test<int>::foo<int>
or by using a lambda, like:
auto func = [&myfoo]() { myfoo.foo(3); };
There is a third way to solve this in C++20 using requires-clause as shown below. Note that the below program is well-formed but gcc and msvc incorrectly rejects it. Only clang accepts it which is the correct behavior. Demo
#include <iostream>
#include <type_traits>
#include <functional>
template <typename T>
class test {
public:
void foo(const T& v) requires std::is_copy_constructible_v<T>{
std::cout << "copy constructible";
}
void foo(const T& v) requires (!std::is_copy_constructible_v<T>) {
std::cout << "non copy constructible";
}
void foo_bar(const T& v){
std::cout << "test";
}
};
int main(int argn, char** argc){
test<int> myfoo;
myfoo.foo(3); //Works
auto func = std::bind(&test<int>::foo_bar, &myfoo, 3); //Works
auto func2 = std::bind(&test<int>::foo, &myfoo, 3); //works
func();
func2();
}
I want to define a template function that gets one argument passed by value for all types but std::string (and const char*).
template<typename T>
void foo( T value )
{
// some code using value
}
The std::string version should behave exactly as the template version, but have its parameter passed by const&.
What is the best approach to do what I want without duplicating the body of foo()?
The best I was able to think is to wrap the code using value inside another function, and then call it inside all versions of foo() (the template version and the std::string overload). Is there another way? For example, is it possible to call the template version from within the std::string overload?
EDIT
What I want to know is a good rule of thumb for avoiding code duplication among various specializations and overloads. What is a good pattern to follow? Shall I define a wrapper function for the body and then call that from within all overloads/specializations, or there is another way?
In order to avoid code duplication, the answer by 101010 can be extended to actually call the template from within the overload:
#include <string>
#include <iostream>
#include <type_traits>
#include <boost/core/demangle.hpp>
template<typename T>
void foo( T value )
{
std::cout << "inside template" << std::endl;
std::cout << boost::core::demangle(typeid(value).name()) << std::endl;
}
void foo(const std::string &value)
{
std::cout << "inside const string overload" << std::endl;
foo<const std::string&>(value);
}
int main()
{
foo(10);
foo(std::string("hello"));
return 0;
}
output
inside template
int
inside const string overload
inside template
std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >
live example
Simple solution: provide an overload for std::string:
void foo( std::string const &value ) {
// some code using value
}
I think what you are looking for is rvalue signature in C++ 11.
Its as simple as:
#include <iostream>
#include <string>
template<typename T>
void foo(T&& value)
{
std::cout << "was passed by refernece:" << std::is_lvalue_reference<T&&>::value << std::endl;
std::cout << value << std::endl;
}
int main()
{
std::string text = "hello";
foo(text);
foo(1);
}
You can either pass the parameter by reference or by value and the rvalue rules will use the appropriate type.
You can define a type-trait-like class that will convert std::string to std::string& and will keep the type for all other types:
template<class T>
struct helper {
typedef T type;
};
template<>
struct helper<std::string> {
typedef std::string& type; // or const std::string& type if you want
};
template<typename T>
void foo( typename helper<T>::type value, T value2 )
{
value = value2;
}
int main()
{
int a = 10;
foo(a, 42);
std::cout << a << std::endl; // prints 10
std::string s = "abc";
foo(s, std::string("def"));
std::cout << s << std::endl; // prints def
}
Full example: http://coliru.stacked-crooked.com/a/96cf78e6c4846172
UPD: as noted by #PiotrSkotnicki, having only one parameter makes type-deduction fail. However, I will keep the answer as it might be helpful in case you indeed have several parameters of type T or if you are ok with specifying explicit template parameter to foo.
UPD2: To solve the type-deduction problem, you may add another wrapper:
template<typename T>
void foo_helper( typename helper<T>::type value )
{
value = T();
}
template<typename T>
void foo(T& value)
{
foo_helper<T>(value);
}
This still might have some problems, so whether this is applicable to your usecase, is up to you to decide.
use std::enable_if + std::is_convertibale:
template<typename T>
typename std::enable_if<!std::is_convertible<T,std::string>::value>::type foo( T value )
{
// some code using value
}
I have the following template function:
template<class T, class F> T function(F& f) {
...
T t;
f(t);
return t;
}
It's expected to be used with F with the form
void some_function(SomeType& s);
in this way
function<SomeType>(some_function);
The first template argument seems redundant because can be deduced from the parameters of the parameter function.
The question is
Exists a way to get rid of the first template parameter?
Something like
template<class F> first_param_type<F> function(F& f) {
...
first_param_type<F> t;
f(t);
return t;
}
So that I can use it as
function(some_function);
template<class T>
T function( void(*f)(T&) ) {
...
T t;
f(t);
return t;
}
solves the problem as stated. The general problem cannot be solved (where F is an arbitrary callable), as callables in C++ can accept more than one type, and deducing what types are acceptable cannot be solved in the general case.
If you had a list of types you support, it an be solved in general.
The basic problem in C++14 is function([](auto&x){ std::cout << x << '\n'; }). The same problem exists in C++11 with function objects with a template operator(). The fact that auto-lambdas are supported in C++14 means that such objects are going to become more and more common in the future.
Consider changing your design so that the signature of your F is T() rather than void(T&). Then we get:
template<class F>
std::result_of_t<F()>
function( F&& f ) {
...
return std::forward<F>(f)();
}
or typename std::result_of<F()>::type in C++11.
I hope I understood your question, maybe I am wrong...
First of all I expect your template function must be called and for the call it needs additional parameters which I could not found in your example code.
But ok, what I expect what you can do:
#include <iostream>
using namespace std;
template <typename RetType, typename ... Parms>
auto TemplateFunction ( RetType(*ptr)(Parms ...), Parms ... parms ) -> RetType
{
RetType ret;
ret = (*ptr)( parms...);
cout << "Value ret in Wrapper is:" << ret << endl;
return ret;
}
double AnyFunc(int a, int b) { return 3.14 * a + b; }
std::string OtherFunc( ) { return "Hallo"; }
int main()
{
double result = TemplateFunction(&AnyFunc, 1,3);
cout << "Result is " << result << endl;
cout << TemplateFunction(&OtherFunc) << endl;
}
As you already mentioned, there is no need to give the return type as additional parameter, because it can be found in the given as type in the presented function pointer to the template.
The wrapper template will work for all return types but not for void!
UPDATE
I absolutely agree with Yakk's answer I just wanted to mention an other but very similar way:
#include <functional>
template < class Type >
Type myFunction( const std::function< void( Type& ) >& aFunction )
{
Type instance;
aFunction( instance );
return instance;
}
EDIT: Just to clarify "t" is successfully called when casted. The compiler knows and does state that it is a function pointer that takes an argument of type int. I supply a null int pointer to break the loop because it is calling itself recursively. It may just be a bug in the compiler.
I am trying to call a function from a template function argument.
I would assume that it would be possible to call the function without explicit casting but that does not seem to be the case. Using VC2013.
template<typename T>
void func(T t)
{
printf("calling func...\n");
if (t)
{
((void(__cdecl*)(int))t)((int)nullptr); // explicit casting is successful
t ((int)nullptr); // compile error: ``term does not evaluate to a function taking 1 arguments``
}
}
void main()
{
auto pe = func < int > ;
auto pf = func < void(__cdecl*)(int) >;
pf(pe);
}
You have the error for func<int> which becomes:
void func(int t)
{
printf("calling func...\n");
if (t)
{
((void(__cdecl*)(int))t)((int)nullptr); // bad casting
t ((int)nullptr); // compile error: int is not a callable object
}
}
When t is an int, of course you can't treat it like a function. You'll have to specialize the template for ints or use a different function. Also, please forget that there are C-style casts, they only serve to shoot yourself into the foot.
I don't understand what do you want exactly. But maybe something like this ?:
#include <iostream>
#include <type_traits>
template<typename T>
void call_helper(T value, std::true_type) // value is function
{
std::cout << "Function" << std::endl;
value(0);
}
template<typename T>
void call_helper(T value, std::false_type) // value is NOT function
{
std::cout << "Not function" << std::endl;
std::cout << value << std::endl;
}
template<typename T>
void call(T value)
{
call_helper(value, std::is_function<typename std::remove_pointer<T>::type>());
}
int main()
{
void (*f)(int) = call<int>;
call(f);
}
live example: http://rextester.com/DIYYZ43213
Consider this simple example code:
#include <functional>
#include <iostream>
void f(bool _switch) {
std::cout << "Nothing really" << std::endl;
}
void f(std::function<double (int)> _f) {
std::cout << "Nothing really, too" << std::endl;
}
int main ( int argc, char* argv[] ) {
f([](int _idx){ return 7.9;});
return 0;
}
It fails to compile:
$ g++ --std=c++11 main.cpp
main.cpp: In function ‘int main(int, char**)’:
main.cpp:15:33: error: call of overloaded ‘f(main(int, char**)::<lambda(int)>)’ is ambiguous
main.cpp:15:33: note: candidates are:
main.cpp:6:6: note: void f(bool)
main.cpp:10:6: note: void f(std::function<double(int)>)
However if I replace the second function with a reference argument it compiles fine. And again if it is replaced by a const reference it fails.
So I have some questions concerning this example:
Why is a lambda function implicitly convertible to bool in the first place?
Why does taking a std::function reference solve the ambiguity?
And most important to me, how can I avoid this problem? I need the second function to take either a (copy of a) std::function or a const reference to it.
A lambda function with no capture can be converted to a regular function pointer, which then has a standard conversion to a bool.
If you take the std::function by non-const reference, then that eliminates it as a candidate, since converting the lambda to a std::function requires a temporary, and a temporary cannot bind to a non-const reference. That just leaves f(bool) as a candidate, so there is no ambiguity.
There are many ways you could avoid the ambiguity. For example, you could create a std::function variable first:
std::function<double(int)> g = [](int _idx){ return 7.9;};
f(g);
or you could cast the lambda:
f(std::function<double(int)>([](int _idx){return 7.9;}));
You could have a helper function:
template<typename T>
std::function<T> make_function(T *f) { return {f}; }
int main ( int argc, char* argv[] ) {
f(make_function([](int _idx){ return 7.9;}));
return 0;
}
or you could grab the particular function you are interested in:
int main ( int argc, char* argv[] ) {
void (*f_func)(std::function<double(int)>) = f;
f_func([](int _idx){ return 7.9;});
return 0;
}
namespace details{
template<class Sig,class=void>
struct invoke {};
template<class F, class...Args>
struct invoke<F(Args...),decltype(void(
std::declval<F>()(std::declval<Args>()...)
))>{
using type=decltype(std::declval<F>()(std::declval<Args>()...));
};
}
template<class Sig>struct invoke:details::invoke<Sig>{};
template<typename Sig, typename T, typename=void>
struct invoke_test:std::false_type {};
template<typename R, typename...Args, typename T>
struct invoke_test<R(Args...), T,
typename std::enable_if<
std::is_convertible<
typename invoke<T(Args...)>::type,
R
>::value
>::type
>:std::true_type {};
template<typename...Args,typename T>
struct invoke_test<void(Args...),T,
decltype( void( typename invoke<T(Args...)>::type ) )
>:std::true_type{};
template<typename Sig, typename T>
constexpr bool invokable() {
return invoke_test<Sig,T>::value;
}
this gives us a pseudo-concept invokable.
We can then use it like:
template<typename F>
typename std::enable_if<invokable<double(int),F>()>::type
f(F&&){
std::cout << "can be invoked\n";
}
void f(bool) {
std::cout << "is bool\n";
}
and bob is your uncle.
The real problem is that std::function<double(int)> 's constructor does not do a similar test, and instead claims (falsely) that it can be constructed from anything at all. This is a flaw in the standard, one I suspect will be fixed once concepts are standardized.
You can get rid of the implicit conversion by creating a helper class
#include <functional>
#include <iostream>
struct Boolean {
bool state;
Boolean(bool b):state(b){}
operator bool(){ return state; }
};
void f(Boolean _switch) {
std::cout << "Nothing really " << _switch << std::endl;
}
void f(std::function<double (int)> _f) {
std::cout << "Nothing really, too" << std::endl;
}
int main ( int argc, char* argv[] ) {
f([](int _idx){ return 7.9;});
f(true);
return 0;
}
Should you ever want to call f with eg. a pointer and expect it to call the first overload you will have to cast it to either bool or add a corresponding constructor / cast to the helper class though.
One more option to Vaughn Cato's answer:
template<typename F>
void f(F _f) {
std::cout << "Nothing really, too: " << _f(3) << std::endl;
}
Now the second overload is a template, so it is chosen for a lambda (or anything), and the first is chosen for bool. So calling f is no more complex than needed.
But, one problem with that is if you want to add more overloads, and another is that the first overload will only be called if there is an exact match to bool.