Compilation error on using boost::future .then() - c++

I am trying to use boost::future .then() functionality.
The snippet is taken from Boost 1.54.0 thread synchronisation documentation
#include <string>
#include <boost/thread/future.hpp>
int main() {
boost::future<int> f1 = boost::async([]() { return 123; });
boost::future<std::string> f2 = f1.then([](boost::future<int> f)->std::string {
int x = f.get();
return ("Done" + std::to_string(x));
});
}
Setup :
Ubuntu 13.04
g++ version g++ (Ubuntu 4.8.1-2ubuntu1~13.04) 4.8.1
Boost version 1.54.0
command line :
g++ then_test.cc -std=c++0x -DBOOST_THREAD_VERSION=4 -I /home/prakash/maidsafe/MaidSafe/build/boost_1_54_0/src/boost -L /home/prakash/maidsafe/MaidSafe/build/boost_1_54_0/src/boost/stage/lib -static -lboost_thread-mt -lboost_date_time-mt -lboost_system-mt -lpthread
Error:
g++ then_test.cc -std=c++0x -DBOOST_THREAD_VERSION=4 -I /home/prakash/maidsafe/MaidSafe/build/boost_1_54_0/src/boost -L /home/prakash/maidsafe/MaidSafe/build/boost_1_54_0/src/boost/stage/lib -static -lboost_thread-mt -lboost_date_time-mt -lboost_system-mt -lpthread
then_test.cc: In function ‘int main()’:
then_test.cc:10:44: error: no matching function for call to ‘boost::future<int>::then(main()::__lambda1)’
});
^
then_test.cc:10:44: note: candidates are:
In file included from then_test.cc:2:0:
/home/prakash/maidsafe/MaidSafe/build/boost_1_54_0/src/boost/boost/thread/future.hpp:1598:9: note: template<class F> boost::future<typename boost::result_of<F(boost::future<R>&)>::type> boost::future<R>::then(F&&) [with F = F; R = int]
then(BOOST_THREAD_FWD_REF(F) func);
^
/home/prakash/maidsafe/MaidSafe/build/boost_1_54_0/src/boost/boost/thread/future.hpp:1598:9: note: template argument deduction/substitution failed:
In file included from then_test.cc:2:0:
/home/prakash/maidsafe/MaidSafe/build/boost_1_54_0/src/boost/boost/thread/future.hpp: In substitution of ‘template<class F> boost::future<typename boost::result_of<F(boost::future<R>&)>::type> boost::future<R>::then(F&&) [with F = F; R = int] [with F = main()::__lambda1]’:
then_test.cc:10:44: required from here
/home/prakash/maidsafe/MaidSafe/build/boost_1_54_0/src/boost/boost/thread/future.hpp:62:29: error: no type named ‘type’ in ‘struct boost::result_of<main()::__lambda1(boost::future<int>&)>’
#define BOOST_THREAD_FUTURE future
^
/home/prakash/maidsafe/MaidSafe/build/boost_1_54_0/src/boost/boost/thread/future.hpp:3840:3: note: in expansion of macro ‘BOOST_THREAD_FUTURE’
BOOST_THREAD_FUTURE<R>::then(BOOST_THREAD_FWD_REF(F) func)
^
In file included from then_test.cc:2:0:
/home/prakash/maidsafe/MaidSafe/build/boost_1_54_0/src/boost/boost/thread/future.hpp:1601:9: note: template<class F> boost::future<typename boost::result_of<F(boost::future<R>&)>::type> boost::future<R>::then(boost::launch, F&&) [with F = F; R = int]
then(launch policy, BOOST_THREAD_FWD_REF(F) func);
^
/home/prakash/maidsafe/MaidSafe/build/boost_1_54_0/src/boost/boost/thread/future.hpp:1601:9: note: template argument deduction/substitution failed:
then_test.cc:10:44: note: cannot convert ‘<lambda closure object>main()::__lambda1{}’ (type ‘main()::__lambda1’) to type ‘boost::launch’
});
Please let me know if I am missing something here.

Passing future by reference to .then() fixes the compilation issue on gcc 4.8 & clang.
For windows and gcc 4.7 we additionally need to define BOOST_RESULT_OF_USE_DECLTYPE. (as per Xeo's comment). For gcc 4.8 & clang it seems available already.
boost::future<std::string> f2 = f1.then([](boost::future<int>& f)->std::string {
^

Related

How to pass function argument to boost::async()

How do I get boost::async to pass a function argument to the function it executes. My code is
#include <iostream>
// This is for the boos version
#include <boost/thread/future.hpp>
using boost::async;
// This is for the standard library version
//~ #include <future>
//~ using std::async;
int f(int x) {
std::cout << " in f " << x << std::endl;
return x+1;
}
int main() {
auto f_res = async(f,3);
std::cout << "f " << f_res.get() << std::endl;
return 0;
}
I compile with
g++ -std=c++14 -lboost_thread -lboost_system -lpthread test_async_boost.cc
, g++ version 5.3.0 and get many errors, complaining about the number of arguments async is willing to take:
test_async_boost_2.cc: In function 'int main()':
test_async_boost_2.cc:16:26: error: no matching function for call to 'async(int (&)(int), int)'
auto f_res = async(f,3);
^
In file included from test_async_boost_2.cc:3:0:
/usr/include/boost/thread/future.hpp:4035:3: note: candidate: template<class F> boost::unique_future<typename boost::result_of<F()>::type> boost::async(F&&)
async(BOOST_THREAD_FWD_REF(F) f) {
^
/usr/include/boost/thread/future.hpp:4035:3: note: template argument deduction/substitution failed:
test_async_boost_2.cc:16:26: note: candidate expects 1 argument, 2 provided
auto f_res = async(f,3);
^
In file included from test_async_boost_2.cc:3:0:
/usr/include/boost/thread/future.hpp:4018:3: note: candidate: template<class R> boost::unique_future<T> boost::async(R (*)())
async(R(*f)()) {
^
/usr/include/boost/thread/future.hpp:4018:3: note: template argument deduction/substitution failed:
test_async_boost_2.cc:16:26: note: candidate expects 0 arguments, 1 provided
auto f_res = async(f,3);
^
In file included from test_async_boost_2.cc:3:0:
/usr/include/boost/thread/future.hpp:3695:3: note: candidate: template<class F> boost::unique_future<typename boost::result_of<typename boost::decay<T>::type()>::type> boost::async(boost::launch, F&&)
async(launch policy, BOOST_THREAD_FWD_REF(F) f) {
^
/usr/include/boost/thread/future.hpp:3695:3: note: template argument deduction/substitution failed:
test_async_boost_2.cc:16:26: note: cannot convert 'f' (type 'int(int)') to type 'boost::launch'
auto f_res = async(f,3);
^
In file included from test_async_boost_2.cc:3:0:
/usr/include/boost/thread/future.hpp:3634:3: note: candidate: template<class R> boost::unique_future<T> boost::async(boost::launch, R (*)())
async(launch policy, R(*f)()) {
^
/usr/include/boost/thread/future.hpp:3634:3: note: template argument deduction/substitution failed:
test_async_boost_2.cc:16:26: note: cannot convert 'f' (type 'int(int)') to type 'boost::launch'
auto f_res = async(f,3);
^
If I switch the commenting in the #include directuves and the using lines, and compile with
g++ -std=c++14 test_async_boost_2.cc -lpthread
I get the desired output:
in f 3
f 4
How do I get boost::async to work with function arguments?
And: Where do I find the reference documentation of boos::async?
In order to pass a function with its arguments to the method accepting a function, you have to use std::bind or boost::bind.

g++ warnings for variable shadowing in lambda expressions

Why does the following code generate a warning when it is compiled with g++ -Wshadow -std=c++14?
template<typename Function>
void f(Function g) {
int x;
g(0);
}
int main() {
auto g = [](auto x) {};
f(g);
return 0;
}
Compilation (assume this code is saved as lambda_shadow.cc):
$ g++ -std=c++14 -Wshadow lambda_shadow.cc
lambda_shadow.cc: In instantiation of ‘main()::<lambda(auto:1)> [with auto:1 = int]’:
lambda_shadow.cc:4:6: required from ‘void f(Function) [with Function = main()::<lambda(auto:1)>]’
lambda_shadow.cc:9:6: required from here
lambda_shadow.cc:8:21: warning: declaration of ‘x’ shadows a previous local [-Wshadow]
auto g = [](auto x) {};
^
lambda_shadow.cc:3:7: note: shadowed declaration is here
int x;
^
This warning is strange because g++ seems to follow the dynamic scoping rules.
I used g++ version 4.9.2 and 5.2.0, and clang++ 4.6 does not generate any warning.
In addition, I noticed that g++ compiles this code without warnings if a type of the lambda argument is specified (i.e., auto g = [](int x) {};).
Does anyone know the reason for this behavior? A bug of g++?

c++11 lambdas doesn't work with boost::concepts

The following code doesn't work with clang 3.3. but it does word with g++ 4.8.1. Boost version is 1.55.
#include <boost/concept_check.hpp>
template <typename X>
class ConceptsBase {};
int main() {
auto l = [](){};
BOOST_CONCEPT_ASSERT((ConceptsBase<decltype(l)>));
return 0;
}
g++ -std=c++0x test.cpp -I /home/wygos/libs/boost_1_55_0/include/ # works fine!
clang++ -std=c++0x test.cpp -I /home/wygos/libs/boost_1_55_0/include/
gives:
test.cpp:9:5: error: non-type template argument refers to function 'failed' that does not have linkage
BOOST_CONCEPT_ASSERT((ConceptsBase<decltype(l)>));
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/wygos/libs/boost_1_55_0/include/boost/concept/assert.hpp:44:5: note: expanded from macro 'BOOST_CONCEPT_ASSERT'
BOOST_CONCEPT_ASSERT_FN(void(*)ModelInParens)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/wygos/libs/boost_1_55_0/include/boost/concept/detail/general.hpp:70:6: note: expanded from macro 'BOOST_CONCEPT_ASSERT_FN'
&::boost::concepts::requirement_<ModelFnPtr>::failed> \
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/wygos/libs/boost_1_55_0/include/boost/concept/detail/general.hpp:38:17: note: non-type template argument refers to function here
static void failed() { ((Model*)0)->~Model(); }
My lucky guess is that it might be connected to:
http://llvm.org/bugs/show_bug.cgi?id=17030

C++ optional<> and delayed construction of noncopyable object

See the below code,
The question is: how can I delay the construction of an object that is non-copyable, using optional<>.
I'm using boost::optional in the example, although I believe its now in the std::optional standard too.
Yes, I could use scoped_ptr<>, however I wanted to allocate on the stack, not the heap.
#include <boost/optional.hpp>
#include <boost/utility.hpp>
using namespace boost;
struct HardFoo : noncopyable { };
int main()
{
optional<HardFoo> ok_1( in_place() ); // OK
// optional<HardFoo> no_1( HardFoo() ); // won't compile
optional<HardFoo> delay_construct;
// delay_construct = HardFoo(); // won't compile
// delay_construct = optional<HardFoo>( in_place() ); // won't compile
// delay_construct.swap( optional<HardFoo>( in_place() ) ); // won't compile
return 0;
}
I'm using g++, I assume it wouldn't matter whether its C++03 or C++11 in this case, as its a fundamental design issue rather than just a stuff up in the code.
As requested, some error messages, for this one, I uncommented:
delay_construct = HardFoo();
$ g++ -g -Wall -o test -I/stuff/boost/ test.cpp
In file included from /stuff/boost/utility.hpp:18:0,
from test.cpp:2:
test.cpp: In instantiation of ‘void boost::optional_detail::optional_base<T>::assign_value(boost::optional_detail::optional_base<T>::argument_type, boost::optional_detail::optional_base<T>::is_not_reference_tag) [with T = HardFoo; boost::optional_detail::optional_base<T>::argument_type = const HardFoo&; boost::optional_detail::optional_base<T>::is_not_reference_tag = mpl_::bool_<false>]’:
/stuff/boost/optional/optional.hpp:307:12: required from ‘void boost::optional_detail::optional_base<T>::assign(boost::optional_detail::optional_base<T>::argument_type) [with T = HardFoo; boost::optional_detail::optional_base<T>::argument_type = const HardFoo&]’
/stuff/boost/optional/optional.hpp:606:9: required from ‘boost::optional<T>& boost::optional<T>::operator=(boost::optional<T>::argument_type) [with T = HardFoo; boost::optional<T> = boost::optional<HardFoo>; boost::optional<T>::argument_type = const HardFoo&]’
test.cpp:14:30: required from here
/stuff/boost/noncopyable.hpp:28:26: error: ‘const boost::noncopyable_::noncopyable& boost::noncopyable_::noncopyable::operator=(const boost::noncopyable_::noncopyable&)’ is private
test.cpp:6:8: error: within this context
In file included from /stuff/boost/optional.hpp:15:0,
from test.cpp:1:
/stuff/boost/optional/optional.hpp:433:69: note: synthesized method ‘HardFoo& HardFoo::operator=(const HardFoo&)’ first required here
In file included from /stuff/boost/utility.hpp:18:0,
from test.cpp:2:
test.cpp: In instantiation of ‘void boost::optional_detail::optional_base<T>::construct(boost::optional_detail::optional_base<T>::argument_type) [with T = HardFoo; boost::optional_detail::optional_base<T>::argument_type = const HardFoo&]’:
/stuff/boost/optional/optional.hpp:308:12: required from ‘void boost::optional_detail::optional_base<T>::assign(boost::optional_detail::optional_base<T>::argument_type) [with T = HardFoo; boost::optional_detail::optional_base<T>::argument_type = const HardFoo&]’
/stuff/boost/optional/optional.hpp:606:9: required from ‘boost::optional<T>& boost::optional<T>::operator=(boost::optional<T>::argument_type) [with T = HardFoo; boost::optional<T> = boost::optional<HardFoo>; boost::optional<T>::argument_type = const HardFoo&]’
test.cpp:14:30: required from here
/stuff/boost/noncopyable.hpp:27:7: error: ‘boost::noncopyable_::noncopyable::noncopyable(const boost::noncopyable_::noncopyable&)’ is private
test.cpp:6:8: error: within this context
In file included from /stuff/boost/optional.hpp:15:0,
from test.cpp:1:
/stuff/boost/optional/optional.hpp:346:8: note: synthesized method ‘HardFoo::HardFoo(const HardFoo&)’ first required here
There is an answer suggesting to use in_place directly,
it works with this:
optional<HardFoo> ok( in_place() );
but not this:
optional<HardFoo> no( in_place<HardFoo>() ); // BAD
The error messages:
$ g++ -g -Wall -o test -I/stuff/boost/ test.cpp
test.cpp: In function ‘int main()’:
test.cpp:15:44: error: no matching function for call to ‘in_place()’
test.cpp:15:44: note: candidates are:
In file included from /stuff/boost/preprocessor/iteration/detail/iter/forward1.hpp:52:0,
from /stuff/boost/utility/in_place_factory.hpp:24,
from /stuff/boost/optional/optional.hpp:37,
from /stuff/boost/optional.hpp:15,
from test.cpp:1:
/stuff/boost/utility/in_place_factory.hpp:73:1: note: template<class A0> boost::in_place_factory1<A0> boost::in_place(const A0&)
/stuff/boost/utility/in_place_factory.hpp:73:1: note: template argument deduction/substitution failed:
test.cpp:15:44: note: candidate expects 1 argument, 0 provided
In file included from /stuff/boost/preprocessor/iteration/detail/iter/forward1.hpp:57:0,
from /stuff/boost/utility/in_place_factory.hpp:24,
from /stuff/boost/optional/optional.hpp:37,
from /stuff/boost/optional.hpp:15,
from test.cpp:1:
/stuff/boost/utility/in_place_factory.hpp:73:1: note: template<class A0, class A1> boost::in_place_factory2<A0, A1> boost::in_place(const A0&, const A1&)
/stuff/boost/utility/in_place_factory.hpp:73:1: note: template argument deduction/substitution failed:
test.cpp:15:44: note: candidate expects 2 arguments, 0 provided
In file included from /stuff/boost/preprocessor/iteration/detail/iter/forward1.hpp:62:0,
from /stuff/boost/utility/in_place_factory.hpp:24,
from /stuff/boost/optional/optional.hpp:37,
from /stuff/boost/optional.hpp:15,
from test.cpp:1:
You need to in_place directly into the object:
delay_construct = boost::in_place<Type>(params);
Note that it appears that boost didn't support default construction through factories (nullary factories) until 1.35.
In C++14, we will have std::optional, which happens to have std::optional::emplace. So you can do:
std::optional<HardFoo> delay_construct;
delay_construct.emplace(constructor_arg_1, constructor_arg_2);

C++11 with gcc 4.6.1 on a mac

I'm new to the mac and trying to get gcc 4.6 working.
I installed MacPorts and installed gcc 4.6.1 (by executing sudo port install gcc46). I'm trying to compile a simple test code that compiles fine on Linux (with gcc 4.6.1 and 4.6.2) and Windows, but I'm getting errors that make me thing there is something wrong with the installed libraries.
#include <iostream>
#include <type_traits>
#include <future>
struct test {
void get() {}
};
/*template<typename Func>
test async(const Func &f) {
f();
return test();
}*/
using namespace std;
int main (int argc, const char * argv[])
{
auto t1 = async([]() -> int{
cout << "This is thread 1" << endl;
return 1;
});
auto t2 = async([]() -> int {
cout << "This is thread 2" << endl;
return 2;
});
std::cout << "This is the main thread" << endl;
t1.get();
t2.get();
return 0;
}
The error messages:
macbook01:Test fozi$ g++ main.cpp -o test -std=c++0x
main.cpp: In function 'int main(int, const char**)':
main.cpp:30:6: error: invalid use of incomplete type 'std::enable_if<true, std::future<int> >::type'
/opt/local/include/gcc46/c++/future:111:11: error: declaration of 'std::enable_if<true, std::future<int> >::type'
main.cpp:30:6: error: unable to deduce 'auto' from '<expression error>'
main.cpp:35:6: error: invalid use of incomplete type 'std::enable_if<true, std::future<int> >::type'
/opt/local/include/gcc46/c++/future:111:11: error: declaration of 'std::enable_if<true, std::future<int> >::type'
main.cpp:35:6: error: unable to deduce 'auto' from '<expression error>'
/opt/local/include/gcc46/c++/future: At global scope:
/opt/local/include/gcc46/c++/future:150:5: error: 'typename std::enable_if<(! std::is_same<typename std::decay<_Functor>::type, std::launch>::value), std::future<decltype (declval<_Fn>()((declval<_Args>)()...))> >::type std::async(_Fn&&, _Args&& ...) [with _Fn = main(int, const char**)::<lambda()>, _Args = {}, typename std::enable_if<(! std::is_same<typename std::decay<_Functor>::type, std::launch>::value), std::future<decltype (declval<_Fn>()((declval<_Args>)()...))> >::type = std::future<int>]', declared using local type 'main(int, const char**)::<lambda()>', is used but never defined [-fpermissive]
/opt/local/include/gcc46/c++/future:150:5: error: 'typename std::enable_if<(! std::is_same<typename std::decay<_Functor>::type, std::launch>::value), std::future<decltype (declval<_Fn>()((declval<_Args>)()...))> >::type std::async(_Fn&&, _Args&& ...) [with _Fn = main(int, const char**)::<lambda()>, _Args = {}, typename std::enable_if<(! std::is_same<typename std::decay<_Functor>::type, std::launch>::value), std::future<decltype (declval<_Fn>()((declval<_Args>)()...))> >::type = std::future<int>]', declared using local type 'main(int, const char**)::<lambda()>', is used but never defined [-fpermissive]
Note that if I use my dummy async function it compiles and runs fine.
I'm kind of stuck, do I have to install a specific library (version)? How do I do that?
I've had similar issues with gcc-4.6.1 and OS X 10.6. The problem is C++0x's thread is not supported at the moment on OS X.
See this post: c++0x, std::thread error (thread not member of std)
If you look in "${prefix}/include/c++/4.6.1/future" header file, you'll see the line:
#if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1) \
&& defined(_GLIBCXX_ATOMIC_BUILTINS_4)
Unfortunately, _GLIBCXX_HAS_GTHREADS evalute to 0 on OS X.
We're getting there
gcc 4.7 (port) compiles this code just fine.
Xcode 4.3 comes with clang 3.1 which is supposed to support this, but it crashes when I try to compile. However I built clang from SVN and replaced the compiler Xcode is using and now it compiles and runs fine as well.
And it only took half a year.
Try g++ -v to get the version of G++ you're using. I'm not using a pre-compiled compiler but perhaps it is the same for you.
The GCC 4.6.0 is installed in /usr/local/bin under the name x86_64-apple-darwin10.7.0-g++
If you still use the simple g++ command, it may still be /usr/bin/g++, which is Apple's llvm-gcc flavor.