Boost logo

Boost Users :

From: Bernhard Glueck (bernhard_at_[hidden])
Date: 2003-03-15 13:31:04


Hi !

I was using boost:function for a while now with success on
Visual C 7.0 ( MSVC 1300 ) .

I was always using the most actual boost 1.30.0 version from the CVS.
Today i updated the CVS again ( after two days of not doing so )
and suddenly my code which relied on boost::function does not compile
anymore.
I think there have some changes been made, so i need to change my code,
but since there is no boost::function
documentation in the CVS yet can someone please enlighten me what has
changed .. ?

Here is the relevant code:
( I have marked the line where compilation fails and provided the exact
error details below )
( This code compiled perfectly two days ago )

Header:

#include <boost/any.hpp>
#include <boost/function.hpp>
#include <boost/intrusive_ptr.hpp>
#include "..\Platform\Config.h"
#include "IType.h"

namespace Fr
{
    namespace Core
    {
        namespace Reflection
        {
            /// Function type for conversions.
            /// Converts value from and stores the result in the target.
            typedef boost::function1< boost::any,boost::any >
ConversionFunction;

            FR_CORE_API void RegisterConversion(
ConversionFunction,const IType &,const IType & );
            FR_CORE_API ConversionFunction * FindConversion( const
IType &,const IType & );
            FR_CORE_API boost::any Convert( const
boost::any &,const IType & );
            FR_CORE_API boost::any Convert( const
boost::any &,const boost::any &);
        }
    }
}

IMplementation:

/ Disable performance warning
#include "..\Platform\Config.h"
#include <vector>
#include <boost/lexical_cast.hpp>
#include "IConverter.h"
#include "..\Debug\Exception.h"

using namespace Fr::Core::Reflection;

struct ConversionInfo
{
    ConversionFunction function;
    const IType * from;
    const IType * to;
};

std::vector< ConversionInfo > sConversions;

void Fr::Core::Reflection::RegisterConversion( ConversionFunction
func,const IType & from,const IType & to )
{
    for ( unsigned i = 0; i < sConversions.size(); i++ )
    {
        if ( *sConversions[i].to == to && *sConversions[i].from == from )
            return;
    }

    // Else add
    ConversionInfo info;
    info.function = func;
    info.from = &from;
    info.to = &to;

    // Store
    sConversions.push_back( info );
}

ConversionFunction * Fr::Core::Reflection::FindConversion( const IType
&from,const IType &to )
{
    // No conversion same type.
    if ( from == to )
        return NULL;

    for ( unsigned int i = 0; i < sConversions.size(); i++ )
    {
        // Check
        if ( *sConversions[i].from == from && *sConversions[i].to == to )
            return &sConversions[i].function;
    }
   
    return NULL;
}

boost::any Fr::Core::Reflection::Convert( const boost::any &from,const
IType & to )
{
    // First we try to get the type from the input data.
    const IType & fromType = GetType(
ConvertCppTypename(from.type().name()) );

    // Check if it worked
    if ( fromType != NullType() )
    {
        if ( fromType == to )
            return from;

        // Try to find conversion.
        ConversionFunction * func = FindConversion( fromType,to );

        // If we have one
        if ( func )
        {
            ConversionFunction convFunc = *func;
            return convFunc( from );
        }
        else
        {
            std::string msg = "Unable to find conversion from: ";
            msg += fromType.GetName();
            msg += " to: ";
            msg += to.GetName();

            Throw(msg);
        }
    }
    else
    {
        std::string msg = "Unable to retrieve type descriptor for data
type: ";
        msg += from.type().name();
        Throw( msg );
    }

    return from;
}

boost::any Fr::Core::Reflection::Convert( const boost::any &from,const
boost::any & to )
{
    // First we try to get the type from the input data.
    const IType & fromType = GetType(
ConvertCppTypename(from.type().name()) );
    const IType & toType = GetType(
ConvertCppTypename(to.type().name()) );

    // Check if it worked
    if ( fromType != NullType() && toType != NullType() )
    {
        if ( fromType == toType )
            return from;

        if ( FindConversion( fromType,toType ) )
        {
            return Convert( from,toType );
        }
        return to;
    }
    else
    {
        return to;
    }

    return to;
}

//
-----------------------------------------------------------------------------
// Standard conversions
//
-----------------------------------------------------------------------------
static boost::any StringToFloat( const boost::any & input )
{
    std::string data = boost::any_cast<std::string> ( input );
    return boost::lexical_cast<float>(data);
}

static boost::any FloatToString( const boost::any & input )
{
    float data = boost::any_cast<float> ( input );
    return std::string("0");
}

static boost::any StringToInt( const boost::any & input )
{
    std::string data = boost::any_cast<std::string> ( input );
    return boost::lexical_cast<int>(data);
}

static boost::any IntToString( const boost::any & input )
{
    int data = boost::any_cast<int> ( input );
    return std::string("0");
}

#include "..\Math\Vector3.h"

static boost::any StringToVec3f( const boost::any & input )
{
    std::string data = boost::any_cast<std::string> ( input );
    Vec3f result;
    sscanf( data.c_str(),"%f;%f;%f",&result.x,&result.y,&result.z);
    return result;
}

static boost::any Vec3fToString( const boost::any & input )
{
    Vec3f data = boost::any_cast<Vec3f> ( input );
    std::string result;
    //result += boost::lexical_cast<std::string> ( data.x );
    result += ";";
    //result += boost::lexical_cast<std::string> ( data.y );
    result += ";";
    //result += boost::lexical_cast<std::string> ( data.z );
    return result;
}

static boost::any BoolToString( const boost::any & input )
{
    bool data = boost::any_cast<bool> ( input );
    if ( data )
        return std::string("True");
    else
        return std::string("False");
}

static boost::any StringToBool( const boost::any & input )
{
    std::string data = boost::any_cast<std::string> ( input );
    if ( data == "True" || data == "true" || data == "TRUE" ||
         data == "On" || data == "on" || data == "ON" )
         return true;
    else return false;
}

//
-----------------------------------------------------------------------------
// Automatic conversion registration
//
-----------------------------------------------------------------------------
void RegisterStandardConversions()
{
  
/////////////////////////////////////////////////////////////////////////////////
// HERE COMPILIATION FAILS: ( Following line )
////////////////////////////////////////////////////////////////////////////

    ConversionFunction stf = &StringToFloat;

///////////////////////////////////////////////////////////////////////////////////
/// VISUAL C ERROR OUTPUT:
//////////////////////////////////////////////////////////////////////////////////
D:\Sdk\boost\boost\type_traits\is_class.hpp(78) : error C2510: 'value' :
left of '::' must be a class/struct/union
        D:\Sdk\boost\boost\type_traits\is_class.hpp(94) : see reference
to class template instantiation 'boost::detail::is_class_impl<T>' being
compiled
        with
        [
            T=boost::any (__cdecl *)(const boost::any &)
        ]
        D:\Sdk\boost\boost\type_traits\is_stateless.hpp(31) : see
reference to class template instantiation 'boost::is_class<T>' being
compiled
        with
        [
            T=boost::any (__cdecl *)(const boost::any &)
        ]
        D:\Sdk\boost\boost\type_traits\is_stateless.hpp(43) : see
reference to class template instantiation
'boost::detail::is_stateless_impl<T>' being compiled
        with
        [
            T=boost::any (__cdecl *)(const boost::any &)
        ]
        D:\Sdk\boost\boost\function\function_base.hpp(193) : see
reference to class template instantiation 'boost::is_stateless<T>' being
compiled
        with
        [
            T=boost::any (__cdecl *)(const boost::any &)
        ]
        D:\Sdk\boost\boost\function\function_template.hpp(431) : see
reference to class template instantiation
'boost::detail::function::get_function_tag<F>' being compiled
        with
        [
            F=boost::any (__cdecl *)(const boost::any &)
        ]
        D:\Sdk\boost\boost\function\function_template.hpp(293) : see
reference to function template instantiation 'void
boost::function1<R,T0,Allocator>::assign_to(Functor)' being compiled
        with
        [
            R=boost::any,
            T0=boost::any,
            Allocator=int,
            Functor=boost::any (__cdecl *)(const boost::any &)
        ]
        \Work\FakedReality\Source\Core\Reflection\IConverter.cpp(214) :
see reference to function template instantiation
'boost::function1<R,T0,Allocator>::function1(const Functor & )' being
compiled
        with
        [
            R=boost::any,
            T0=boost::any,
            Allocator=int,
            Functor=boost::any (__cdecl *)(const boost::any &)
        ]
D:\Sdk\boost\boost\type_traits\is_class.hpp(78) : error C2065: 'ice_not'
: undeclared identifier
D:\Sdk\boost\boost\type_traits\is_class.hpp(78) : error C2679: binary
'<' : no operator found which takes a right-hand operand of type '' (or
there is no acceptable conversion)
D:\Sdk\boost\boost\type_traits\is_class.hpp(78) : error C2955:
'boost::type_traits::ice_and' : use of class template requires template
argument list
        D:\Sdk\boost\boost\type_traits\detail\ice_and.hpp(25) : see
declaration of 'boost::type_traits::ice_and'
D:\Sdk\boost\boost\type_traits\is_class.hpp(78) : error C2955:
'boost::type_traits::ice_and' : use of class template requires template
argument list
        D:\Sdk\boost\boost\type_traits\detail\ice_and.hpp(25) : see
declaration of 'boost::type_traits::ice_and'
D:\Sdk\boost\boost\type_traits\is_class.hpp(78) : error C2039: 'value' :
is not a member of 'operator``global namespace'''
D:\Sdk\boost\boost\type_traits\is_class.hpp(78) : error C2065: 'value' :
undeclared identifier
D:\Sdk\boost\boost\type_traits\is_class.hpp(78) : error C2676: binary
'>' : '' does not define this operator or a conversion to a type
acceptable to the predefined operator
D:\Sdk\boost\boost\type_traits\is_class.hpp(78) : error C2056: illegal
expression

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    RegisterConversion( stf,typeof<std::string>(),typeof<float>() );

    ConversionFunction fts = &FloatToString;
    RegisterConversion( fts,typeof<float>(),typeof<std::string>() );

    ConversionFunction its = &IntToString;
    RegisterConversion( its,typeof<int>(),typeof<std::string>() );
   
    ConversionFunction sti = &StringToInt;
    RegisterConversion( sti,typeof<std::string>(),typeof<int>() );

    ConversionFunction v3fts = &Vec3fToString;
    RegisterConversion( v3fts,typeof<Vec3f>(),typeof<std::string>() );

    ConversionFunction stv3f = &StringToVec3f;
    RegisterConversion( stv3f,typeof<std::string>(),typeof<Vec3f>() );

    ConversionFunction stb = &StringToBool;
    RegisterConversion( stb,typeof<std::string>(),typeof<bool> () );

    ConversionFunction bts = &BoolToString;
    RegisterConversion( bts,typeof<bool>(),typeof<std::string>());
}

////////////////////// SECOND Problem
As you may note all conversions from data types to std::string are
commented out !
This is because boost::lexical_cast fails to compile in DEBUG mode ( it
compiles fine in RELEASE Mode
and also works like a charm in RELEASE mode )

Thanks for your time
Bernhard Glück


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net