Template function with std::async in clang - c++

I was looking at the example for std::async here, as follows:
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <future>
template <typename RAIter>
int parallel_sum(RAIter beg, RAIter end)
{
auto len = std::distance(beg, end);
if(len < 1000)
return std::accumulate(beg, end, 0);
RAIter mid = beg + len/2;
auto handle = std::async(std::launch::async,
parallel_sum<RAIter>, mid, end);
int sum = parallel_sum(beg, mid);
return sum + handle.get();
}
int main()
{
std::vector<int> v(10000, 1);
std::cout << "The sum is " << parallel_sum(v.begin(), v.end()) << '\n';
}
I tried compiling it with the web compiler for Clang 3.4 and it resulted in the output The sum is instead of the expected The sum is 1000.
I copied the example and compiled with clang 3.5-1ubuntu1 / gcc 4.8 on Ubuntu 14.04.1 64-bit using the following command:
clang++ -g main.cpp -std=c++1y -o out -pthread;
I get the following error:
main.cpp:15:19: error: no matching function for call to 'async'
auto handle = std::async(std::launch::async,
^~~~~~~~~~
main.cpp:24:35: note: in instantiation of function template specialization
'parallel_sum<__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> >
> >' requested here
std::cout << "The sum is " << parallel_sum(v.begin(), v.end()) << '\n';
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/future:1523:5: note:
candidate template ignored: substitution failure [with _Fn = int
(__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > >,
__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > >), _Args =
<__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > > &,
__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > > &>]:
function cannot return function type 'int (__gnu_cxx::__normal_iterator<int *,
std::vector<int, std::allocator<int> > >, __gnu_cxx::__normal_iterator<int *,
std::vector<int, std::allocator<int> > >)'
async(launch __policy, _Fn&& __fn, _Args&&... __args)
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/future:1543:5: note:
candidate template ignored: substitution failure [with _Fn = std::launch, _Args = <int
(__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > >,
__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > >),
__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > > &,
__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > > &>]: no
type named 'type' in 'std::result_of<std::launch (int
(*)(__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > >,
__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > >),
__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > > &,
__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > > &)>'
async(_Fn&& __fn, _Args&&... __args)
^
1 error generated.
make: *** [all] Error 1
Is this a bug in clang, gcc, libstdc++, or am I missing something?

I think this is a bug in clang++. Unless there's a strange restricted rule that I'm not aware of, an id-expression referring to a function is an lvalue. However, clang++ makes a distinction between function template specializations and ordinary functions in the deduction for a universal reference:
#include <iostream>
template<class T>
void print_type()
{
std::cout << __PRETTY_FUNCTION__ << "\n";
}
template <class T>
int foo(bool) { return 42; }
int bar(bool) { return 42; }
template<class T>
void deduce(T&&)
{
print_type<T>();
}
int main()
{
deduce(foo<bool>);
deduce(bar);
}
Output, clang++ up to and including an early 3.5:
void print_type() [T = int (bool)]
void print_type() [T = int (&)(bool)]
Live example
std::result_of is used in libstdc++'s implementation of std::async to get the return type of the function (snippet from here):
template<typename _Fn, typename... _Args>
future<typename result_of<_Fn(_Args...)>::type>
async(launch __policy, _Fn&& __fn, _Args&&... __args)
If we pass foo<bool> as the second argument, clang++ deduces _Fn == int (bool).
The type of the function (object) is combined with the argument types for result_of. This is probably a relict of C++03, where we didn't have variadic templates yet. The argument types are passed to allow result_of to resolve overloaded functions like an overloaded operator() in case _Fn is a class type.
However, if _Fn is deduced not to a function reference, but to a function type, the combination _Fn(_Args...) forms an illegal type: a function returning a function:
_Fn == int(bool)
_Args... == bool
==> _Fn(_Args...) == int(bool)(bool)
But there's more to it: The above declaration of async is defective, see LWG 2021. Howard Hinnant changed the declaration in libc++ to:
template <class F, class... Args>
future < typename result_of<
typename decay<F>::type(typename decay<Args>::type...)
>::type
>
async(launch policy, F&& f, Args&&... args);
so libc++ decays the function to a function pointer. The problem caused by the missing lvalue reference disappears.

Related

How could I implement a vector of stack?

I am currently trying to implement a class with a vector of stacks. The class shall work as a stack to other objects but distribute the data to different stacks of a maximum size internally. If a stack is full a new one is created and pushed to the internal vector.
My current approach generates errors:
prog.cpp: In instantiation of ‘SetOfStack<T>::SetOfStack(int) [with T = int]’:
prog.cpp:54:32: required from here
prog.cpp:13:17: error: no matching function for call to ‘std::vector<std::stack<int, std::deque<int, std::allocator<int> > >, std::allocator<std::stack<int, std::deque<int, std::allocator<int> > > > >::push_back(std::stack<int, std::deque<int, std::allocator<int> > >*)’
stacks.push_back( new stack<T> );
^
/usr/include/c++/4.8/bits/stl_vector.h:901:7: note: no known conversion for argument 1 from ‘std::stack<int, std::deque<int, std::allocator<int> > >*’ to ‘const value_type& {aka const std::stack<int, std::deque<int, std::allocator<int> > >&}’
/usr/include/c++/4.8/bits/stl_vector.h:919:7: note: void std::vector<_Tp, _Alloc>::push_back(std::vector<_Tp, _Alloc>::value_type&&) [with _Tp = std::stack<int, std::deque<int, std::allocator<int> > >; _Alloc = std::allocator<std::stack<int, std::deque<int, std::allocator<int> > > >; std::vector<_Tp, _Alloc>::value_type = std::stack<int, std::deque<int, std::allocator<int> > >]
push_back(value_type&& __x)
^
/usr/include/c++/4.8/bits/stl_vector.h:919:7: note: no known conversion for argument 1 from ‘std::stack<int, std::deque<int, std::allocator<int> > >*’ to ‘std::vector<std::stack<int, std::deque<int, std::allocator<int> > >, std::allocator<std::stack<int, std::deque<int, std::allocator<int> > > > >::value_type&& {aka std::stack<int, std::deque<int, std::allocator<int> > >&&}’
prog.cpp: In instantiation of ‘void SetOfStack<T>::push(T) [with T = int]’:
prog.cpp:55:21: required from here
prog.cpp:22:25: error: ‘__gnu_cxx::__alloc_traits<std::allocator<std::stack<int, std::deque<int, std::allocator<int> > > > >::value_type’ has no member named ‘push_back’
stacks[current_stack].push_back(new stack<T>);
^
prog.cpp: In instantiation of ‘T SetOfStack<T>::pop() [with T = int]’:
prog.cpp:56:27: required from here
prog.cpp:34:25: error: ‘__gnu_cxx::__alloc_traits<std::allocator<std::stack<int, std::deque<int, std::allocator<int> > > > >::value_type’ has no member named ‘pop_back’
stacks[current_stack].pop_back();
^
Sample Code:
#include <iostream>
#include <stack>
#include <vector>
using namespace std;
template <class T>
class SetOfStack {
public:
SetOfStack( int max_size ): current_stack(0), max_stack_size(max_size) {
stacks.reserve(10);
stacks.push_back( new stack<T> );
}
~SetOfStack() {
stacks.clear();
}
void push( T value ) {
stacks[current_stack].push(value);
if(stacks[current_stack].size() > max_stack_size) {
stacks[current_stack].push_back(new stack<T>);
current_stack++;
if(current_stack % 10 == 0 && current_stack > stacks.size()) {
stacks.reserve(stacks.size() + 10);
}
}
}
T pop() {
T value = stacks[current_stack].top();
stacks[current_stack].pop();
if(stacks[current_stack].size() == 0 && current_stack != 0 ) {
stacks[current_stack].pop_back();
current_stack--;
}
}
T popAt( int index ) {
T value = stacks[index].top();
stacks[index].pop();
}
private:
int current_stack;
int max_stack_size;
vector< stack<T> > stacks;
};
int main() {
// Test code
SetOfStack<int> s_o_s(3);
s_o_s.push(1);
cout << s_o_s.pop() << endl;
return 0;
}
The error you're getting is this line:
stacks.push_back( new stack<T> );
As well as this line:
stacks[current_stack].push_back(new stack<T>);
Because you have declared stacks as a non-pointer:
vector< stack<T> > stacks;
So you want to use just stack<T>() instead of new stack<T>
Additionally, std::stack does not have a function push_back, you need to use push instead.
stacks.push_back(stack<T>());
stacks[current_stack].push(value);
As well as pop and not pop_back():
stacks[current_stack].pop();
At which point, you no longer need the deletes I mentioned in my original comment, since it looks like you were not intending to call new

what is wrong using for_each/mem_fun

I am using C++98.
I have the following code:
#include <vector>
#include <algorithm>
#include <functional>
struct Foo {};
void
add_each(std::vector<std::vector<Foo*> > &vv, const Foo *f)
{
for_each(vv.begin(), vv.end(), std::bind2nd(std::mem_fun(&std::vector<Foo*>::push_back), f));
}
Basically I like to add an element to the end of every vector.
G++ complains the line of for_each.
In file included from /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/algorithm:62,
from 1.c:2:
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/bits/stl_algo.h: In function ‘_Funct std::for_each(_IIter, _IIter, _Funct) [with _IIter = __gnu_cxx::__normal_iterator<std::vector<Foo*, std::allocator<Foo*> >*, std::vector<std::vector<Foo*, std::allocator<Foo*> >, std::allocator<std::vector<Foo*, std::allocator<Foo*> > > > >, _Funct = std::binder2nd<std::mem_fun1_t<void, std::vector<Foo*, std::allocator<Foo*> >, Foo* const&> >]’:
1.c:10: instantiated from here
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/bits/stl_algo.h:4200: error: no match for call to ‘(std::binder2nd<std::mem_fun1_t<void, std::vector<Foo*, std::allocator<Foo*> >, Foo* const&> >) (std::vector<Foo*, std::allocator<Foo*> >&)’
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/backward/binders.h:146: note: candidates are: typename _Operation::result_type std::binder2nd<_Operation>::operator()(const typename _Operation::first_argument_type&) const [with _Operation = std::mem_fun1_t<void, std::vector<Foo*, std::allocator<Foo*> >, Foo* const&>]
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/backward/binders.h:152: note: typename _Operation::result_type std::binder2nd<_Operation>::operator()(typename _Operation::first_argument_type&) const [with _Operation = std::mem_fun1_t<void, std::vector<Foo*, std::allocator<Foo*> >, Foo* const&>]
Do you see what is wrong?
for_each will dereference the iterator and pass that result to its unary function argument. In your case, that type is std::vector<Foo*>&. However, std::mem_fun requires a pointer to the object it's wrapping, and not a reference. You should use std::mem_fun_ref instead.
void
add_each(std::vector<std::vector<Foo*> > &vv, const Foo *f)
{
for_each(vv.begin(), vv.end(),
std::bind2nd(std::mem_fun_ref(&std::vector<Foo*>::push_back), f));
}
Live example
You're trying to push_back a const Foo* into a vector of Foo*. Either make the vector hold const Foo* or change the type of parameter f to Foo*.
If you want that your code would be also compiled with standard libraries of the C++ 2011 then I suggest the following solution
void ( std::vector<Foo *>:: *pf )( Foo * const &);
pf = &std::vector<Foo *>::push_back;
std::for_each( vv.begin(), vv.end(),
std::bind2nd( std::mem_fun_ref( pf ), f ) );
The problem is that in the C++ 2011 member function push_back is overloaded.

boost::bind don't compile with member template function

I just write an simple example to test boost::bind. I use it to instantiate a template member function, but it won't compile with g++ 4.6.0. I don't know what's the problem.
Here's the code:
#include <boost/bind.hpp>
struct Functor
{
void operator()()
{
}
};
struct DerivedFinishAction
{
DerivedFinishAction()
{}
void Inc()
{
}
template <typename T>
void TmplFunc(T t)
{
(boost::bind(&DerivedFinishAction::BindFunc<T>, this , t))();
}
template <typename T>
void BindFunc(T t)
{
t();
}
void Func()
{
Functor f;
TmplFunc(f); // this is OK
TmplFunc(boost::bind(&DerivedFinishAction::Inc, this)); // compile error
}
};
int main(int argc, char *argv[])
{
return 0;
}
And g++ gives the following errors:
In file included from /usr/include/boost/bind.hpp:22:0,
from testBind.cpp:1:
/usr/include/boost/bind/bind.hpp: In member function ‘void boost::_bi::list2<A1, A2>::operator()(boost::_bi::type<void>, F&, A&, int) [with F = boost::_mfi::mf1<void, DerivedFinishAction, boost::_bi::bind_t<void, boost::_mfi::mf0<void, DerivedFinishAction>, boost::_bi::list1<boost::_bi::value<DerivedFinishAction*> > > >, A = boost::_bi::list0, A1 = boost::_bi::value<DerivedFinishAction*>, A2 = boost::_bi::bind_t<void, boost::_mfi::mf0<void, DerivedFinishAction>, boost::_bi::list1<boost::_bi::value<DerivedFinishAction*> > >]’:
/usr/include/boost/bind/bind_template.hpp:20:59: instantiated from ‘boost::_bi::bind_t<R, F, L>::result_type boost::_bi::bind_t<R, F, L>::operator()() [with R = void, F = boost::_mfi::mf1<void, DerivedFinishAction, boost::_bi::bind_t<void, boost::_mfi::mf0<void, DerivedFinishAction>, boost::_bi::list1<boost::_bi::value<DerivedFinishAction*> > > >, L = boost::_bi::list2<boost::_bi::value<DerivedFinishAction*>, boost::_bi::bind_t<void, boost::_mfi::mf0<void, DerivedFinishAction>, boost::_bi::list1<boost::_bi::value<DerivedFinishAction*> > > >, boost::_bi::bind_t<R, F, L>::result_type = void]’
testBind.cpp:24:5: instantiated from ‘void DerivedFinishAction::TmplFunc(T) [with T = boost::_bi::bind_t<void, boost::_mfi::mf0<void, DerivedFinishAction>, boost::_bi::list1<boost::_bi::value<DerivedFinishAction*> > >]’
testBind.cpp:37:58: instantiated from here
/usr/include/boost/bind/bind.hpp:313:9: error: invalid use of void expression
Can anybody help explain this? Why the first instantiation is OK while the second one causes compile error?
There's a (non-obvious) feature of boost::bind involved here. http://www.boost.org/libs/bind/#nested_binds
If you write:
void func1(int len) {return len+1;};
int func2(std::string str) {return str.length();};
assert(
boost::bind(func1, boost::bind(func2, _1) )("Hello")
== 6 );
boost::bind assumes that what you meant is "run func2 on "Hello", then run func1 on the result". This allows more interesting partial function application.
In your program, you have an expression which amounts to:
boost::bind(&DerivedFinishAction::BindFunc<...>,
this,
boost::bind(&DerivedFinishAction::Inc, this))
So boost::bind tries to figure out how to run DerivedFinishAction::Inc on it arguments, so it can pass that result into DerivedFinishAction::BindFunc<...>. But DerivedFinishAction::Inc returns void, which cannot be passed into DerivedFinishAction::BindFunc<...>. Thus you get a compiler error:
/usr/include/boost/bind/bind.hpp:313:9: error: invalid use of void expression
Edit: Per the documentation, you can use protect to achieve your desired behavior:
#include <boost/bind/protect.hpp>
...
TmplFunc(boost::protect(boost::bind(&DerivedFinishedAction::Inc, this))); // no longer an error
...

Why doesn't my custom iterator work with the STL copy?

I wrote an OutputIterator for an answer to another question. Here it is:
#include <queue>
using namespace std;
template< typename T, typename U >
class queue_inserter {
queue<T, U> &qu;
public:
queue_inserter(queue<T,U> &q) : qu(q) { }
queue_inserter<T,U> operator ++ (int) { return *this; }
queue_inserter<T,U> operator * () { return *this; }
void operator = (const T &val) { qu.push(val); }
};
template< typename T, typename U >
queue_inserter<T,U> make_queue_inserter(queue<T,U> &q) {
return queue_inserter<T,U>(q);
}
This works great for this little copy function:
template<typename II, typename OI>
void mycopy(II b, II e, OI oi) {
while (b != e) { *oi++ = *b++; }
}
But it doesn't work at all for the STL copy from algorithms. Here are the wonderful C++ errors I get:
i.cpp:33: error: specialization of ‘template<class _Iterator> struct std::iterator_traits’ in different namespace
/usr/include/c++/4.0.0/bits/stl_iterator_base_types.h:127: error: from definition of ‘template<class _Iterator> struct std::iterator_traits’
/usr/include/c++/4.0.0/bits/stl_algobase.h: In function ‘_OI std::__copy_aux(_II, _II, _OI) [with _II = int*, _OI = queue_inserter<int, std::deque<int, std::allocator<int> > >]’:
/usr/include/c++/4.0.0/bits/stl_algobase.h:335: instantiated from ‘static _OI std::__copy_normal<true, false>::copy_n(_II, _II, _OI) [with _II = __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, _OI = queue_inserter<int, std::deque<int, std::allocator<int> > >]’
/usr/include/c++/4.0.0/bits/stl_algobase.h:387: instantiated from ‘_OutputIterator std::copy(_InputIterator, _InputIterator, _OutputIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, _OutputIterator = queue_inserter<int, std::deque<int, std::allocator<int> > >]’
i.cpp:53: instantiated from here
/usr/include/c++/4.0.0/bits/stl_algobase.h:310: error: no type named ‘value_type’ in ‘struct std::iterator_traits<queue_inserter<int, std::deque<int, std::allocator<int> > > >’
/usr/include/c++/4.0.0/bits/stl_algobase.h:315: error: no type named ‘value_type’ in ‘struct std::iterator_traits<queue_inserter<int, std::deque<int, std::allocator<int> > > >’
/usr/include/c++/4.0.0/bits/stl_algobase.h:315: error: ‘__value’ is not a member of ‘<declaration error>’
/usr/include/c++/4.0.0/bits/stl_algobase.h:335: instantiated from ‘static _OI std::__copy_normal<true, false>::copy_n(_II, _II, _OI) [with _II = __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, _OI = queue_inserter<int, std::deque<int, std::allocator<int> > >]’
/usr/include/c++/4.0.0/bits/stl_algobase.h:387: instantiated from ‘_OutputIterator std::copy(_InputIterator, _InputIterator, _OutputIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, _OutputIterator = queue_inserter<int, std::deque<int, std::allocator<int> > >]’
i.cpp:53: instantiated from here
/usr/include/c++/4.0.0/bits/stl_algobase.h:317: error: ‘__simple’ is not a valid template argument for type ‘bool’ because it is a non-constant expression
/usr/include/c++/4.0.0/bits/stl_algobase.h:317: error: ‘copy’ is not a member of ‘<declaration error>’
Here is the driver:
int main() {
vector<int> v;
v.push_back( 1 );
v.push_back( 2 );
queue<int> q;
copy( v.begin(), v.end(), make_queue_inserter(q) );
while (q.size() > 0) {
cout << q.front() << endl;
q.pop();
}
}
Why in the world is it specializing iterator_traits. What's wrong with my iterator? Can't I just write my own simple iterators?
Your queue_inserter needs to be derived from std::iterator so that all the typedefs such as value_type are properly defined since these are used inside STL algorithms This definition works:
template< typename T, typename U >
class queue_inserter : public std::iterator<std::output_iterator_tag, T>{
queue<T, U> &qu;
public:
queue_inserter(queue<T,U> &q) : qu(q) { }
queue_inserter<T,U> operator ++ (int) { return *this; }
queue_inserter<T,U> operator ++ () { return *this; }
queue_inserter<T,U> operator * () { return *this; }
void operator = (const T &val) { qu.push(val); }
};
Derive it from std::iterator. If you are interested the Dr. Dobb's has an article about custom containers and iterators.
Your iterator doesn't meet the requirement for an 'assignable' type which is a requirement for an output iterator because it contains a reference and assignable types need to ensure that after t = u that t is equivalent to u.
You can provide a suitable specialization for iterator_traits for your iterator either by deriving from a specialization of std::iterator or by providing one explicitly.
namespace std
{
template<> struct iterator_traits<MyIterator>
{
typedef std::output_iterator_tag iterator_category;
typedef void value_type;
typedef void difference_type;
};
}
#include <queue>
#include <algorithm>
#include <iterator>
#include <iostream>
using namespace std;
template< typename T, typename U >
class queue_inserter
{
queue<T, U> &qu;
public:
// for iterator_traits to refer
typedef output_iterator_tag iterator_category;
typedef T value_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef T& reference;
queue_inserter(queue<T,U> &q) : qu(q) { }
queue_inserter<T,U>& operator ++ () { return *this; }
queue_inserter<T,U> operator * () { return *this; }
void operator = (const T &val) { qu.push(val); }
};
template< typename T, typename U >
queue_inserter<T,U> make_queue_inserter(queue<T,U> &q)
{
return queue_inserter<T,U>(q);
}
int main()
{
// uses initalizer list (C++0x), pass -std=c++0x to g++
vector<int> v({1, 2, 3});
queue<int, deque<int>> q;
copy(v.cbegin(), v.cend(), make_queue_inserter(q));
while (!q.empty())
{
cout << q.front() << endl;
q.pop();
}
}
This should do it with iterator_traits; a helper struct in <iterator> which defines all types an iterator should typically define. Functions in <algorithm>, refer to these types when required like iterator_traits<it>::iterator_category or say iterator_traits<it>::value_type, etc. Just defining them inside one's custom iterator would do the trick. This is the modern way of writing iterators, as opposed to the classical way of inheriting from std::iterator. Having a look at <iterator> reveals that even std::iterator defines these types i.e. iterator_category, difference_type, etc. This is the reason, when inherited from std::iterator, the derived iterator class gets these due to heredity.

Why does this code using `::boost::bind` get a compiler error?

This code:
#include <boost/signals.hpp>
#include <boost/bind.hpp>
#include <boost/mem_fn.hpp>
#include <iostream>
class Recorder : public ::boost::signals::trackable {
public:
void signalled() {
const void *me = this;
::std::cerr << "Recorder at " << me << " signalled!\n";
}
};
void signalled()
{
::std::cerr << "Signalled!\n";
}
int main(int argc, const char *argv[])
{
::boost::signal<void ()> sig;
sig.connect(&signalled);
{
Recorder r;
sig.connect(::boost::bind(&Recorder::signalled, &r, _1));
sig();
}
sig();
return 0;
}
is generating these compiler errors:
In file included from move_constructor.cpp:2:
/usr/include/boost/bind.hpp: In instantiation of ‘boost::_bi::result_traits<boost::_bi::unspecified, void (Recorder::*)()>’:
/usr/include/boost/bind/bind_template.hpp:15: instantiated from ‘boost::_bi::bind_t<boost::_bi::unspecified, void (Recorder::*)(), boost::_bi::list2<boost::_bi::value<Recorder*>, boost::arg<1> > >’
move_constructor.cpp:25: instantiated from here
/usr/include/boost/bind.hpp:67: error: ‘void (Recorder::*)()’ is not a class, struct, or union type
In file included from /usr/include/boost/function/detail/maybe_include.hpp:13,
from /usr/include/boost/function/function0.hpp:11,
from /usr/include/boost/signals/signal_template.hpp:38,
from /usr/include/boost/signals/signal0.hpp:24,
from /usr/include/boost/signal.hpp:19,
from /usr/include/boost/signals.hpp:9,
from move_constructor.cpp:1:
/usr/include/boost/function/function_template.hpp: In static member function ‘static void boost::detail::function::void_function_obj_invoker0<FunctionObj, R>::invoke(boost::detail::function::function_buffer&) [with FunctionObj = boost::_bi::bind_t<boost::_bi::unspecified, void (Recorder::*)(), boost::_bi::list2<boost::_bi::value<Recorder*>, boost::arg<1> > >, R = void]’:
/usr/include/boost/function/function_template.hpp:904: instantiated from ‘void boost::function0<R>::assign_to(Functor) [with Functor = boost::_bi::bind_t<boost::_bi::unspecified, void (Recorder::*)(), boost::_bi::list2<boost::_bi::value<Recorder*>, boost::arg<1> > >, R = void]’
/usr/include/boost/function/function_template.hpp:720: instantiated from ‘boost::function0<R>::function0(Functor, typename boost::enable_if_c<boost::type_traits::ice_not::value, int>::type) [with Functor = boost::_bi::bind_t<boost::_bi::unspecified, void (Recorder::*)(), boost::_bi::list2<boost::_bi::value<Recorder*>, boost::arg<1> > >, R = void]’
/usr/include/boost/function/function_template.hpp:1040: instantiated from ‘boost::function<R()>::function(Functor, typename boost::enable_if_c<boost::type_traits::ice_not::value, int>::type) [with Functor = boost::_bi::bind_t<boost::_bi::unspecified, void (Recorder::*)(), boost::_bi::list2<boost::_bi::value<Recorder*>, boost::arg<1> > >, R = void]’
/usr/include/boost/signals/slot.hpp:111: instantiated from ‘boost::slot<SlotFunction>::slot(const F&) [with F = boost::_bi::bind_t<boost::_bi::unspecified, void (Recorder::*)(), boost::_bi::list2<boost::_bi::value<Recorder*>, boost::arg<1> > >, SlotFunction = boost::function<void()>]’
move_constructor.cpp:25: instantiated from here
/usr/include/boost/function/function_template.hpp:152: error: no match for call to ‘(boost::_bi::bind_t<boost::_bi::unspecified, void (Recorder::*)(), boost::_bi::list2<boost::_bi::value<Recorder*>, boost::arg<1> > >) ()’
This is with g++ 4.4.1 on a Fedora 11 box with the Fedora 11 boost-1.37.0 package installed.
This code seems perfectly kosher to me. I don't understand what's going on here, and the maze of template expansion related errors is very confusing. Does anybody know what the problem is?
sig.connect(::boost::bind(&Recorder::signalled, &r, _1));
What is the _1 placeholder left for here? It's unneeded, connect expects void -> void function. If you'll remove the needless placeholder, the code will compile.
You provide &Recorder::signalled -- a member function of type void Recorder::(void), correctly bind a Recorder pointer, changing it to void -> void, and then additionally leave a placeholder _1 -- what is obviously wrong.