Produce the error
Foo<T>::visitor': not a valid using-declaration at non-class scope
Please post the full code that produces this error.
Originally Posted by ma740988
Not following you on 'why did you make the visitor a member variable anyway'. The goal is to have the user pass in their own class type.
'visitor' is a member variable of Foo<T> in your code. Why? The class type is passed by the user as template argument. You don't need a member variable for that.
Here's the code with your suggestion. Note I commented out "T visitor" in Foo and I've changed the first argument in doWork to "boost::apply_visitor ( T(), intField ) ;
Code:
# include <iostream>
# include <map>
# include <boost/variant.hpp>
# include <boost/mpl/vector.hpp>
# include <boost/mpl/contains.hpp>
# include <boost/bind.hpp>
# include <boost/utility/enable_if.hpp>
// Generic visitor that does magical dispatching of
// types and delegates passes down to your visitor only
// those types specified in a type list.
template <typename Visitor, typename TypeList>
struct lets_see :
public boost::static_visitor<void>,
public Visitor
{
template <typename T>
inline void operator ()
( T v, typename boost::enable_if<
typename boost::mpl::contains< TypeList, T >::type >::type *dummy = NULL ) const
{
Visitor::operator () (v);
}
template <typename T>
inline void operator ()
( T v,
typename boost::disable_if <
typename boost::mpl::contains< TypeList, T >::type >::type *dummy = NULL ) const
{}
};
struct nil { int x ; };
struct example_visitor
{
typedef lets_see
< example_visitor,
boost::mpl::vector<nil, char, int > > value_type;
inline void operator () (char v) const {
std::cout << "character detected" << std::endl;
}
inline void operator () (int v) const {
std::cout << "integer detected=" << v << std::endl;
}
inline void operator () (nil v) const {
std::cout << "nil detected=" << v.x << std::endl;
}
};
template < typename T >
class Foo {
protected :
typedef boost::variant <
nil, char, int, double
> sql_field;
// T visitor ;
typedef std::map< unsigned int , Foo <T>* > FooMap;
static FooMap mFooMap;
public :
static Foo <T>* createInstance( unsigned int const );
void Register( unsigned int const, Foo< T >* );
virtual void doWork () ;
};
template < typename T>
typename Foo<T>::FooMap Foo<T>::mFooMap;
template < typename T>
Foo<T>* Foo<T>::createInstance( unsigned int const in ) {
FooMap::iterator it = mFooMap.find( in );
if ( it != mFooMap.end() ) {
return ( it->second );
} else {
return 0 ;
}
}
template < typename T>
void Foo<T>::Register( unsigned int const in, Foo<T>* factory ) {
mFooMap.insert( FooMap::value_type( in, factory ) );
}
template < typename T>
void Foo<T>::doWork() {}
template <typename T>
class Bar : public Foo <T> {
// Bar( const bar& );
public :
Bar( unsigned int a ) {
Register ( a, this ) ;
}
static Bar mBar;
void doWork () {
sql_field intField ( 1 );
// using Foo<T>::visitor ;
// boost::apply_visitor ( typename Foo<T>::visitor(), intField );
boost::apply_visitor ( T(), intField );
std::cout << "Work done" << std::endl;
}
};
template < typename T>
Bar<T> Bar<T>::mBar;
int main() {
try {
typedef Foo <example_visitor::value_type> FooValueType;
//Bar <example_visitor::value_type> b ( 5 );
Bar <FooValueType> b ( 5 );
Foo <FooValueType>* ptr = Foo<FooValueType>::createInstance ( 5 ) ;
if ( ptr ) {
ptr->doWork();
}
} catch ( const std::exception& e ) {
std::cout << e.what() << std::endl;
}
std::cout << "[done]" << std::endl;
std::cin.get() ;
}
Here's the error.
1>------ Build started: Project: experiment, Configuration: Debug x64 ------
1>Build started 2/18/2013 12:42:56 PM.
1>InitializeBuildStatus:
1> Touching "x64\Debug\experiment.unsuccessfulbuild".
1>ClCompile:
1> main.cpp
1>main.cpp(107): error C2780: 'boost::apply_visitor_delayed_t<Visitor> boost::apply_visitor(Visitor &)' : expects 1 arguments - 2 provided
1> c:\lib\boost\boost_1_49_0\boost/variant/detail/apply_visitor_delayed.hpp(81) : see declaration of 'boost::apply_visitor'
1> main.cpp(103) : while compiling class template member function 'void Bar<T>::doWork(void)'
1> with
1> [
1> T=FooValueType
1> ]
1> main.cpp(120) : see reference to class template instantiation 'Bar<T>' being compiled
1> with
1> [
1> T=FooValueType
1> ]
1>main.cpp(107): error C2780: 'Visitor::result_type boost::apply_visitor(const Visitor &,Visitable1 &,Visitable2 &)' : expects 3 arguments - 2 provided
1> c:\lib\boost\boost_1_49_0\boost/variant/detail/apply_visitor_binary.hpp(166) : see declaration of 'boost::apply_visitor'
1>main.cpp(107): error C2780: 'Visitor::result_type boost::apply_visitor(Visitor &,Visitable1 &,Visitable2 &)' : expects 3 arguments - 2 provided
1> c:\lib\boost\boost_1_49_0\boost/variant/detail/apply_visitor_binary.hpp(141) : see declaration of 'boost::apply_visitor'
1>main.cpp(107): error C2893: Failed to specialize function template 'Visitor::result_type boost::apply_visitor(const Visitor &,Visitable &)'
1> With the following template arguments:
1> 'Foo<T>'
1> with
1> [
1> T=example_visitor::value_type
1> ]
1> 'Foo<T>::sql_field'
1> with
1> [
1> T=FooValueType
1> ]
1>main.cpp(107): error C2893: Failed to specialize function template 'Visitor::result_type boost::apply_visitor(Visitor &,Visitable &)'
1> With the following template arguments:
1> 'Foo<T>'
1> with
1> [
1> T=example_visitor::value_type
1> ]
1> 'Foo<T>::sql_field'
1> with
1> [
1> T=FooValueType
1> ]
1>
1>Build FAILED.
1>
1>Time Elapsed 00:00:02.66
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Last edited by ma740988; February 18th, 2013 at 11:45 AM.
Reason: added compilation error
Here's the code with your suggestion. Note I commented out "T visitor" in Foo and I've changed the first argument in doWork to "boost::apply_visitor ( T(), intField ) ;
The boost library is at version 1.53. According to your compiler listing, you are using 1.49.
You are 4 versions behind from the latest build. I would suggest you try the latest build of Boost first, as numerous fixes go into boost on each revision, including fixes that affect compiler compilation issues.
I've _already_ posted the _full_ code. Here's doWork with Foo<T>::visitor as the first argument.
No need for the attitude. The compiler error you posted now is different from the one you posted before. That one didn't make sense for the line of code you posted; it was about a using declaration.
Anyway, try including the correct header: <boost/variant/apply_visitor.hpp>.
Cheers, D Drmmr
Please put [code][/code] tags around your code to preserve indentation and make it more readable.
As long as man ascribes to himself what is merely a posibility, he will not work for the attainment of it. - P. D. Ouspensky
Well the error means what it says. Why are you calling "apply_visitor" with two arguments? I just looked at the boost headers, and indeed, boost::apply_visitor takes one argument.
The other "apply_visitor" functions are members of the apply_visitor_delayed_t class. You're calling the global (or boost namespace, non-class version), and that takes only 1 argument.
Code:
boost::apply_visitor ( T(), intField );
This is calling the non-class version, and from what I can see, this is not overloaded to take two or more arguments.
Regards,
Paul McKenzie
Last edited by Paul McKenzie; February 19th, 2013 at 10:47 AM.
I think I'm back to my original (sort of) question then. Consider:
Code:
class Foo {
// Generic visitor that does magical dispatching of
// types and delegates passes down to your visitor only
// those types specified in a type list.
template <typename Visitor, typename TypeList>
struct lets_see :
public boost::static_visitor<void>,
public Visitor
{
template <typename T>
inline void operator ()
( T v, typename boost::enable_if<
typename boost::mpl::contains< TypeList, T >::type >::type *dummy = NULL ) const
{
Visitor::operator () (v);
}
template <typename T>
inline void operator ()
( T v,
typename boost::disable_if <
typename boost::mpl::contains< TypeList, T >::type >::type *dummy = NULL ) const
{}
};
struct nil { int x ; };
struct example_visitor
{
typedef lets_see
< example_visitor,
boost::mpl::vector<nil, char, int > > value_type;
inline void operator () (char v) const {
std::cout << "character detected" << std::endl;
}
inline void operator () (int v) const {
std::cout << "integer detected=" << v << std::endl;
}
inline void operator () (nil v) const {
std::cout << "nil detected=" << v.x << std::endl;
}
};
protected :
typedef boost::variant <
nil, char, int, double
> sql_field;
example_visitor::value_type visitor ;
typedef std::map< unsigned int , Foo* > FooMap;
static FooMap mFooMap;
public :
static Foo* createInstance( unsigned int const );
void Register( unsigned int const, Foo* );
virtual void doWork () ;
};
Foo::FooMap Foo::mFooMap;
Foo* Foo::createInstance( unsigned int const in ) {
FooMap::iterator it = mFooMap.find( in );
if ( it != mFooMap.end() ) {
return ( it->second );
} else {
return 0 ;
}
}
void Foo::Register( unsigned int const in, Foo* factory ) {
mFooMap.insert( FooMap::value_type( in, factory ) );
}
void Foo::doWork() {}
class Bar : public Foo {
// Bar( const bar& );
public :
Bar( unsigned int a ) {
Register ( a, this ) ;
}
static Bar mBar;
void doWork () {
sql_field intField ( 1 );
boost::apply_visitor ( visitor, intField );
std::cout << "Work done" << std::endl;
}
};
Bar Bar::mBar = 0;
int main() {
try {
Bar b ( 5 );
Foo * ptr = Foo::createInstance ( 5 ) ;
if ( ptr ) {
ptr->doWork();
}
} catch ( const std::exception& e ) {
std::cout << e.what() << std::endl;
}
std::cout << "[done]" << std::endl;
std::cin.get() ;
}
This is the non-templated version of the code that I experimented with which produces the desired result. Trouble is within the Foo class the user defined type ("example_visitor::value_type visitor" ) is hard coded. i.e
Code:
example_visitor::value_type visitor ;
My desire is to accept whatever user defined type is presented as opposed to the hard coded (example_visitor::value_type) version, hence why I went the template route. The question then becomes, how can I my objective?
Bookmarks