Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GCC cannot deduce auto return type from a template function?

I've a simple template function do_something which returns an integer: 123.

template<typename T>
auto do_something(T input) {
  std::this_thread::sleep_for(std::chrono::seconds(1));
  return 123;
}

int main(int argc, char *argv[]) {
  std::function<int(void)> function = std::bind(do_something<int>, 12);
  function();
  return 0;
}

With GCC 6.1.1, I get this error:

test.cpp: In function ‘int main(int, char**)’:
test.cpp:16:70: error: no matching function for call to ‘bind(<unresolved overloaded function type>, int)’
   std::function<int(void)> function = std::bind(do_something<int>, 12);
                                                                      ^
In file included from /usr/include/c++/6.1.1/thread:39:0,
                 from test.cpp:4:
/usr/include/c++/6.1.1/functional:1331:5: note: candidate: template<class _Func, class ... _BoundArgs> typename std::_Bind_helper<std::__is_socketlike<_Func>::value, _Func, _BoundArgs ...>::type std::bind(_Func&&, _BoundArgs&& ...)
     bind(_Func&& __f, _BoundArgs&&... __args)
     ^~~~
/usr/include/c++/6.1.1/functional:1331:5: note:   template argument deduction/substitution failed:
test.cpp:16:70: note:   couldn't deduce template parameter ‘_Func’
   std::function<int(void)> function = std::bind(do_something<int>, 12);
                                                                      ^
In file included from /usr/include/c++/6.1.1/thread:39:0,
                 from test.cpp:4:
/usr/include/c++/6.1.1/functional:1359:5: note: candidate: template<class _Result, class _Func, class ... _BoundArgs> typename std::_Bindres_helper<_Result, _Func, _BoundArgs>::type std::bind(_Func&&, _BoundArgs&& ...)
     bind(_Func&& __f, _BoundArgs&&... __args)
     ^~~~
/usr/include/c++/6.1.1/functional:1359:5: note:   template argument deduction/substitution failed:
test.cpp:16:70: note:   couldn't deduce template parameter ‘_Result’
   std::function<int(void)> function = std::bind(do_something<int>, 12);

As you can see, the compiler cannot deduce the result type of the function.

Note that: clang++ 3.8.0 can compile that without any errors.

So my question: is there a way to specify the expected return value from a template function like in this case?

like image 992
BiagioF Avatar asked Jul 04 '16 00:07

BiagioF


People also ask

Can function return type be auto?

In C++14, you can just use auto as a return type.

What are the differences in type deduction for function template arguments and the auto keyword?

auto type deduction is usually the same as template type deduction, but auto type deduction assumes that a braced initializer represents a std::initializer_list , and template type deduction doesn't. auto in a function return type or a lambda parameter implies template type deduction, not auto type deduction.


1 Answers

It looks like the compiler isn't sure about the type of the do_something<int> - and I'm not sure if this is a compiler issue, or a language issue - but you can force the compiler to get its types sorted out by using do_something<int> in a relatively trivial way before hand. For example the following compiles OK with both gcc and clang trunk versions (according to godbolt).

#include <functional>

template<typename T>
auto do_something(T input) {
  return 123;
}

// Make the compiler workout the type of do_something<int> so we can use it later.
auto f = do_something<int>;

int main(int argc, char *argv[]) {
  std::function<int(void)> function = std::bind(do_something<int>, 12);
  function();
  return 0;
}
like image 87
Michael Anderson Avatar answered Oct 15 '22 08:10

Michael Anderson