Boost logo

Boost :

From: Ed Brey (brey_at_[hidden])
Date: 2000-08-30 14:20:43


"any" looks like a very useful class. Some comments:

Design:

Why is there not a non-const version of to_ptr? I.e.
template<ValueType>
ValueType* to_ptr();

How about a cast member function to complement the any_cast global:
class any { ...
 template<ValueType>
 ValueType cast() const;
};

This would allow a convenience such as:
pass_me_int(a.cast<int>());

without declaring the variable that copy_to would require. Using any_cast
in this sense would be redendant, since the fact that the source is of type
any shows up in both the variable name "a" and the name "any_cast".

You almost could get rid of any_cast altogether by doing
 int i = any("3").cast<int>();
instead of
 int i = any_cast<int>("3");

except I do like how the bottom one looks. I'm not entirely sure where
any_cast would be used versus other casts. I assume it comes into play once
people start defining any-compatible conversions on their classes.

Implementation:

I did some hacking to get any to work on VC6SP4. Here's what I did:

1. Add a dummy parameter on to_ptr, so it looks like:
        template<typename ValueType>
        const ValueType *to_ptr(const ValueType&) const

Likewise change calls to to_ptr<ValueType>() to to_ptr(ValueType()).

2. Replaced the copy constructor with a specialization, to avoid the bogus
ambiguity. Reordered constructors accordingly.

template<>
any(const any &other)
  : content(other.content ? other.content->clone() : 0)
{
}

3. Replaced operator=(const any&) with a specialized version, which
reimplements the constructor functionality instead of calling swap.

template<>
any &operator=(const any &rhs)
{
 delete content;
 content = rhs.content ? rhs.content->clone() : 0;
    return *this;
}

4. Pulled type_info into std, i.e.

namespace std {using ::type_info;}

I don't know why I had to do that since the STLport code looks like it is
doing it for me. I haven't tried looking at the preprocessed output, which
would probably tell the story.

Given these changes, and changes to the use of to_ptr in your test harness,
you test harness compiles, runs, and reports success. Of course all these
hacks would only be for the case of VC. The only exception is that if we
can't find a better to_ptr workaround, we'd want to provide a compatibility
overload of to_ptr, a la:

#ifndef PLEASE_FIX_YOUR_COMPILER_BILL

  template<typename ValueType>
  const ValueType *to_ptr() const
  {
    return type_info() == typeid(ValueType)
       ? &static_cast<holder<ValueType> *>(content)->held
       : 0;
  }

  // Depricated from birth: This exists to allow code that
  // has the VC to_ptr() workaround to also work with
  // conforming compilers.
  template<typename ValueType>
  const ValueType *to_ptr(const ValueType&) const
  {
     return to_ptr<ValueType>();
  }

#else // VC

  // Work-around for VC. Not part of "official" interface.
  template<typename ValueType>
  const ValueType *to_ptr(const ValueType&) const
      // Dummy parameter to help VC.
  {
    return type_info() == typeid(ValueType)
       ? &static_cast<holder<ValueType> *>(content)->held
       : 0;
  }

#endif

Another choice is to have to_ptr provide the pointer via a reference
parameter, like copy_to does with the value; however, I'm wary of that idea
since it starts bending our design to appease a broken compiler, which I do
not like.

Documentation:

In the section "ValueType requirements", there is an extra "s" at the of
"Another distinguishing features".

I'd prefer to avoid using coding styles in documentation that cause problems
in the real world. In particular, I'd like to see the explicit std:: and
boost:: scoping used. Also, in count_all(), instead of further engraining
std::endl, perhaps something like:

cout <<
    "#empty == " << count_if(values.begin(), values.end(), is_empty) << "\n"
    "#int == " << count_if(values.begin(), values.end(), is_int) << "\n"
    "#const char * == " << count_if(values.begin(), values.end(),
is_char_ptr) << "\n"
    "#string == " << count_if(values.begin(), values.end(), is_string) <<
'\n';


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk