Hi,
Please take a look at the code below.
The point is that for_each_treenode calls for_each_treenode_child. It seems
to me that
bind(Print, ref(cout), _1)(&t);
is not the same as
Print(cout, &t);
But if this is the case, how come that
for_each_treenode_child(&t, bind(Print, ref(cout), _1));
compiles and works without problem?
The compiler I use is VC 7.1.
Thx,
Gus
----------------------------------------------------------------------
// xBindTemplFuncPtr.cpp : Defines the entry point for the console
application.
//
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <string>
#include
#include
using namespace std;
using namespace boost;
template
void for_each_treenode_child(TTree* t, TFunc f)
{
for_each(t->children.begin(), t->children.end(),
f );
}
template
void for_each_treenode(TTree *t, TFunc f)
{
void (*thisFunc)(TTree*, TFunc) = for_each_treenode;
// COMPILER BUG WORKAROUND - NOT RELEVANT NOW
for_each_treenode_child(
t,
boost::bind(thisFunc, _1, f)
);
f(t);
}
struct Tree {
typedef vector Container;
typedef Container::const_iterator const_iterator;
typedef Container::iterator iterator;
const_iterator begin() const { return children.begin(); }
const_iterator end() const { return children.end(); }
iterator begin() { return children.begin(); }
iterator end() { return children.end(); }
Tree(const string& sData):data(sData) {}
vector children;
string data;
};
void Print(ostream& out, const Tree* pTree) {
out << pTree->data << " ";
}
void PrintStd(const Tree* pTree) {
Print(cout, pTree);
}
int _tmain(int argc, _TCHAR* argv[])
{
Tree t("t"), t1("t1"), t2("t2"), t11("t11"), t12("t12"), t21("t21");
t.children.push_back(&t1);
t1.children.push_back(&t11);
t1.children.push_back(&t12);
t.children.push_back(&t2);
t2.children.push_back(&t21);
Print(cout, &t); // WORKS
bind(Print, ref(cout), _)(&t); // GENERATES ERROR (1)
for_each_treenode(&t, bind(Print, ref(cout), _1)); // GENERATES ERROR (2)
cout << endl;
for_each_treenode(&t, PrintStd); // WORKS
cout << endl;
for_each_treenode_child(&t, bind(Print, ref(cout), _1)); // WORKS
cout << endl;
return 0;
}
------------------------------------------------------------------------
Error for (1):
error C2664: 'boost::_bi::bind_t::result_type
boost::_bi::bind_t::operator
()(A1 & ) const' : cannot convert parameter 1 from 'Tree *__w64
' to 'Tree
*__w64 & '
with
[
R=void,
F=void (__cdecl *)(std::ostream &,const Tree *),
L=boost::_bi::list2,boost::arg<
1>>::B1,boost::_bi::list_av_2std::ostream,boost::
arg<1>>::B2>,
A1=Tree *__w64
]
A reference that is not to 'const' cannot be bound to a non-lvalue
Error for (2):
c:\Program Files\Microsoft Visual Studio .NET
2003\Vc7\include\boost\bind.hpp(246) : error
C2664: 'void (TTree *,TFunc)' : cannot convert parameter 2 from
'boost::_bi::result_traits::type' to 'boost::_bi::bind_t'
with
[
TTree=Tree,
TFunc=boost::_bi::bind_t,boost::arg
<1>>::B1,boost::_bi::list_av_2std::ostream,boost:
:arg<1>>::B2>>
]
and
[
R=void,
F=void (__cdecl *)(std::ostream &,const Tree *)
]
and
[
R=void,
F=void (__cdecl *)(std::ostream &,const Tree *),
L=boost::_bi::list2,boost::arg<
1>>::B1,boost::_bi::list_av_2std::ostream,boost::
arg<1>>::B2>
]
Expressions of type void cannot be converted to other types
c:\Program Files\Microsoft Visual Studio .NET
2003\Vc7\include\boost\bind\bind_template.hpp(33) : see reference to
function template
instantiation 'R boost::_bi::list2::operator
()::result_type,void(__cdecl *)(TTree
*,TFunc),boost::_bi::list1>(boost::_bi::type<T>,void,A &)' being
compiled
with
[
R=boost::_bi::bind_t,boost::arg
<1>>::B1,boost::_bi::list_av_2std::ostream,boost:
:arg<1>>::B2>>::
result_type,
A1=boost::_bi::list_av_2,boost::_bi::bind_t,boost::arg
<1>>::B1,boost::_bi::list_av_2std::ostream,boost:
:arg<1>>::B2>>>:
:B1,
A2=boost::_bi::list_av_2,boost::_bi::bind_t,boost::arg
<1>>::B1,boost::_bi::list_av_2std::ostream,boost:
:arg<1>>::B2>>>:
:B2,
F=void (__cdecl *)(std::ostream &,const Tree *),
L=boost::_bi::list2,boost::arg<
1>>::B1,boost::_bi::list_av_2std::ostream,boost::
arg<1>>::B2>,
TTree=Tree,
TFunc=boost::_bi::bind_t,boost::arg
<1>>::B1,boost::_bi::list_av_2std::ostream,boost:
:arg<1>>::B2>>,
T=boost::_bi::bind_t,boost::arg
<1>>::B1,boost::_bi::list_av_2std::ostream,bo
ost::arg<1>>::B2>>::result_type,
A=boost::_bi::list1
]
c:\Program Files\Microsoft Visual Studio .NET
2003\Vc7\include\algorithm(21) : see
reference to function template instantiation
'boost::_bi::bind_t::result_type
boost::_bi::bind_t::operator ()::value_type>(A1
& )' being
compiled
with
[
R=void,
F=void (__cdecl *)(Tree *,boost::_bi::bind_t,boost::arg
<1>>::B1,boost::_bi::list_av_2std::ostream,boost:
:arg<1>>::B2>>),
L=boost::_bi::list2,boost::_bi::bind_t,boost::arg
<1>>::B1,boost::_bi::list_av_2std::ostream,boost:
:arg<1>>::B2>>>:
:B1,boost::_bi::list_av_2,boost::_bi::bind_t,boost::arg
<1>>::B1,boost::_bi::list_av_2std::ostream,boost:
:arg<1>>::B2>>>:
:B2>,
_Ty=Tree *,
A1=std::allocator::value_type
]
c:\PROG\VCPP\xBindTemplFuncPtr\xBindTemplFuncPtr.cpp(18) : see
reference to function
template instantiation '_Fn1
std::for_each::iterator,TFunc>(_InIt,_InIt,_Fn1)' being
compiled
with
[
_Fn1=boost::_bi::bind_t,boost::arg
<1>>::B1,boost::_bi::list_av_2std::ostream,boost:
:arg<1>>::B2>>),
boost::_bi::list2,boost::_bi::bind_t,boost::arg
<1>>::B1,boost::_bi::list_av_2std::ostream,boost:
:arg<1>>::B2>>>:
:B1,boost::_bi::list_av_2,boost::_bi::bind_t,boost::arg
<1>>::B1,boost::_bi::list_av_2std::ostream,boost:
:arg<1>>::B2>>>:
:B2>>,
_Ty=Tree *,
TFunc=boost::_bi::bind_t,boost::arg
<1>>::B1,boost::_bi::list_av_2std::ostream,boost:
:arg<1>>::B2>>),
boost::_bi::list2,boost::_bi::bind_t,boost::arg
<1>>::B1,boost::_bi::list_av_2std::ostream,boost:
:arg<1>>::B2>>>:
:B1,boost::_bi::list_av_2,boost::_bi::bind_t,boost::arg
<1>>::B1,boost::_bi::list_av_2>::B2>>>::B2>>,
_InIt=std::vector::iterator
]
c:\PROG\VCPP\xBindTemplFuncPtr\xBindTemplFuncPtr.cpp(29) : see
reference to function
template instantiation 'void
for_each_treenode_child>(TTree
*,TFunc)' being compiled
with
[
TTree=Tree,
R=void,
F=void (__cdecl *)(Tree *,boost::_bi::bind_t,boost::arg
<1>>::B1,boost::_bi::list_av_2std::ostream,boost:
:arg<1>>::B2>>),
L=boost::_bi::list2,boost::_bi::bind_t,boost::arg
<1>>::B1,boost::_bi::list_av_2std::ostream,boost:
:arg<1>>::B2>>>:
:B1,boost::_bi::list_av_2,boost::_bi::bind_t,boost::arg
<1>>::B1,boost::_bi::list_av_2std::ostream,boost:
:arg<1>>::B2>>>:
:B2>,
TFunc=boost::_bi::bind_t,boost::arg
<1>>::B1,boost::_bi::list_av_2std::ostream,boost:
:arg<1>>::B2>>),
boost::_bi::list2,boost::_bi::bind_t,boost::arg
<1>>::B1,boost::_bi::list_av_2std::ostream,boost:
:arg<1>>::B2>>>:
:B1,boost::_bi::list_av_2,boost::_bi::bind_t,boost::arg
<1>>::B1,boost::_bi::list_av_2std::ostream,boost::arg<1>>::B2>>>::B2>>
]
c:\PROG\VCPP\xBindTemplFuncPtr\xBindTemplFuncPtr.cpp(68) : see
reference to function
template instantiation 'void
for_each_treenode>(TTree
*,TFunc)' being compiled
with
[
R=void,
F=void (__cdecl *)(std::ostream &,const Tree *),
L=boost::_bi::list2,boost::arg<
1>>::B1,boost::_bi::list_av_2std::ostream,boost::
arg<1>>::B2>,
TTree=Tree,
TFunc=boost::_bi::bind_t,boost::arg
<1>>::B1,boost::_bi::list_av_2std::ostream,boost:
:arg<1>>::B2>>
]
c:\Program Files\Microsoft Visual Studio .NET
2003\Vc7\include\boost\bind.hpp(246) : error
C2664: 'void (TTree *,TFunc)' : cannot convert parameter 1 from
'boost::_bi::result_traits::type' to 'Tree *'
with
[
TTree=Tree,
TFunc=boost::_bi::bind_t,boost::arg
<1>>::B1,boost::_bi::list_av_2std::ostream,boost:
:arg<1>>::B2>>
]
and
[
R=void,
F=void (__cdecl *)(std::ostream &,const Tree *)
]
Expressions of type void cannot be converted to other types