Domanda

Given a function such as:

template< typename T >
void function1( const T &t )
{
  function2( boost::lexical_cast<std::string>(t) );
}

What kind of overhead is incurred if the type passed to function1 is already a std::string?

Does the overhead vary, depending on the type I'm lexical_cast-ing to?

Is it superfluous to make an overloaded function to bypass the cast? E.g.:

void function1( const std::string &t )
{
  function2( t );
}

template< typename T >
void function1( const T &t )
{
  function1( boost::lexical_cast<std::string>(t) );
}

The version of boost may be relevent to your answer, as I understand that lexical_cast has received a few optimizations across revisions.

È stato utile?

Soluzione

Since the documentation doesn't offer anything on this topic, I dug into the lexical_cast source (1.51.0) and found that it does some compile-time checking on the types and decides a specific "caster class" that does the conversion. In case source and target are the same, this "caster class" will simply return the input.

Pseudo-codified and simplified from source (boost/lexical_cast.hpp:2268):

template <typename Target, typename Source>
Target lexical_cast(const Source &arg)
{
    static if( is_character_type_to_character_type<Target, src> ||
               is_char_array_to_stdstring<Target, src> ||
               is_same_and_stdstring<Target, src> )
    //         ^-- optimization for std::string to std::string and similar stuff
    {
      return arg;
    }
    else
    {
      /* some complicated stuff */
    }
}

I can't directly see any optimizations for other identity casts, though, and looking through the normally selected lexical_cast_do_cast "caster class" is making my head hurt. :(

Altri suggerimenti

http://www.boost.org/doc/libs/1_51_0/doc/html/boost_lexical_cast/performance.html

Consider this link, string to string is very fast.

All the tests measure execution speed in milliseconds for 10000 iterations of the following code blocks:

    typedef BOOST_DEDUCED_TYPENAME ::boost::type_traits::ice_or<
            ::boost::detail::is_xchar_to_xchar<Target, src >::value,
            ::boost::detail::is_char_array_to_stdstring<Target, src >::value,
            ::boost::type_traits::ice_and<
                 ::boost::is_same<Target, src >::value,
                 ::boost::detail::is_stdstring<Target >::value
            >::value
    > shall_we_copy_t;

In our case shall_we_copy_t::value will be true, since 3-rd case work for us (Target and src are equal types and Target type is std::basic_string).

    typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c<
        shall_we_copy_t::value,
        ::boost::detail::lexical_cast_copy<src >,
        BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c<
             shall_we_copy_with_dynamic_check_t::value,
             ::boost::detail::lexical_cast_dynamic_num<Target, src >,
             ::boost::detail::lexical_cast_do_cast<Target, src >
        >::type
    >::type caster_type;

Since, shall_we_copy_t::value is true, our caster_type will be lexical_cast_copy

return caster_type::lexical_cast_impl(arg);

So, will be called lexical_cast_copy::lexical_cast_impl, which is very simple

    template <typename Source>
    struct lexical_cast_copy
    {
        static inline Source lexical_cast_impl(const Source &arg)
        {
            return arg;
        }
    };
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top