Channels ▼
RSS

C/C++

Conversations: I'd Hold Anything for You [1]


December 2001 C++ Experts Forum/Conversations

When the solution came, it wasn't where we had expected it.

We had been concentrating on the alien artifacts left strewn about the alien city buried out here under the European ice. So much of our time had been spent in here, underground, and I missed not being able to take off-duty time out on the surface and take in the silent majesty of King Jupiter filling the sky. But the surface was not safe, not now, with occupying forces on their way.

Using Jäger's new information about the alien language, we had just managed to activate several of the devices, although so far we couldn't tell what they did. We knew we should be careful, but we hadn't the luxury of time for that. The whole purpose, I realized, was for our leaders' faction to gain control of the alien technology, especially if it had military applications. The opposing faction was taking a rather dim view, and I wondered if we hadn't been overrun by them already. It couldn't be long now, days or hours.

But the solution wasn't in the artifacts. It was in the Ballroom.

The dark, icebound city was full of unexplored chambers and chasms, hallways and dead ends. Of the ones we'd found, the most intriguing was the Ballroom — our name for an immense room empty but for three 10-foot-diameter metallic balls fixed suspended in midair. How they were suspended, we had no idea, but it was when we found some of the city's power controls that they came alive.

I was there when it happened. "What the—" started one of the techs with us, but then he stopped. That was all any of us could say just then.

Each of the balls showed a different scene. In one, we could see a brightly lit field of yellowish grasses with what looked like trees in the near distance. In another ball was a beach scene at dusk. The third showed a metallic room much like those here in the buildings, filled with rows of chest-high cabinets.

We stared, and when nothing else happened immediately, we began to move around the balls. The scenes shifted, as though we were really walking around and looking through each ball like a hole into another place, but behind the ball our original room still stood as solid as ever.

"What's in those balls? Are those pictures, or... or where are those places?" Jeannine said, hushed, when she found her voice. A tech, brought out of his wonder by the words, remembered to hurry off to call our ranking officer, who undoubtedly would call Major Gilb.

"I don't know," I said slowly, awed but curious. "They could hold anything. And they could lead anywhere..."


It was rather quiet around work. Many of the staff had left early for the holidays. I, on the other hand, had not been around long enough to accrue much vacation time, so I had to work right up to the holiday shutdown. Of course, this made it much more difficult to get help when I started running into brick walls, like the one I was facing now.

I needed to have a variable that could hold any type of data. My first instinct was to use a template — after all, they're great for generic programming:

template <typename ValueType>
class multiType
{
    ValueType value_;
public:
    multiType(const ValueType &t) : value_(t) {}
    operator ValueType() { return value_; }
};

Unfortunately, I quickly ran into the first wall — there were places in the code where one variable might have to hold different types of information during its lifetime, like this:

{
    multiType<const char *> multiA("Hello, World");
    // ... some code ...
    multiType<long> multiB(99L);
    // ... some more code ...
    multiA = multiB; // Oops -- can't convert from long to const char *.
}

At this point, I needed multiA to forget that it started life as a multiType<const char *> and start acting like it was a multiType<long>. It started to look like I had two choices — a union or a void pointer. I knew enough of the dangers of void pointers, so I decided to use a union:

class multiType
{
    enum ValueType { Long, ConstCharPtr };
    union
        {
        const char * c_;
        long l_;
    } value_;
    ValueType currentType_;
public:
    multiType(const char * c);
    multiType & operator =(const char * c);
    operator const char *();

    multiType(long);
    multiType & operator =(long);
        operator long();
};

By wrapping the union in a class, I had achieved some degree of encapsulation. At least the conversion operators could check that the value type being held was appropriate. I wasn't looking forward to the copy-and-paste exercise ahead of me, to implement all the overloaded constructors and conversion operators that would eventually be needed. (long and const char * were only the tip of the iceberg.)

"You need any."

I jumped at the Guru's voice — almost as much as I used to when I was still an intern. Even with the office as quiet as it was, I had still failed to hear her approach. "Uh," I stammered, "do I need any what?"

"No, my child," she smiled, shutting the large tome in her hand, "that was not a question; that was a statement. You need any."

"Oookay," I replied. I toyed with the idea of using my deer-in-the-headlights look, but decided to go for the direct approach instead and asked: "Ah, would you mind elaborating slightly?"

"A thousand pardons, my apprentice," the Guru bowed. I began wondering why she was in her full Guru act with the office as empty as it was — then I saw Bob heading towards the kitchen for a fresh latte. I knew that the full Guru shtick was used mainly for two reasons: to scare fresh, young recruits, and to annoy the bejeepers out of Bob. "I keep forgetting that you are barely a novitiate," she continued, "and not yet fully trained in the ways of the Programmer." I bristled slightly at that — but then I realized she was right. The more I learned, the less I knew, it seemed.

"I am referring to the Boost library's any class," the Guru continued.

"What's the Boost library? I haven't heard of it."

She smiled a smile of mild surprise. "Indeed? You should. The Boost library is a collection of C++ source libraries. Boost was founded by some of the blessed disciples on the C++ Standards Committee."

"Oh, so it's related to the Standard?"

"Not directly," the Guru replied. "The founding members of Boost are not-so-coincidentally members of the C++ Standards Committee, but otherwise Boost has no official connection with ISO or any other standards body. The blessed writings available at the Boost website, <www.boost.org>, are intended to be candidates for proposal as new standard library items in the next revision of the Holy Standard, but of course there is no guarantee that they will be accepted by the Committee."

"Ah," I ahhed, as I digested that. "So what is this any class you mentioned?"

"The any class, simply put, allows a variable to hold any type of value. An any could hold anything. For example," she picked up the marker and began writing on my whiteboard:

#include <iostream>
#include <boost/any.hpp>
const char * initialMessage = "Snowflakes keep falling on my head";
int main()
{
 boost::any multiA(42L);
 boost::any multiB(initialMessage);
 multiA = multiB;
 std::cout << boost::any_cast<const char *>(multiA) << std::endl;
}

"In this parable, multiA begins life holding a long. The assignment from multiB essentially converts multiA into a const char *. The output of the program, therefore, will be 'Snowflakes keep falling on my head'," the Guru concluded as she put down the marker.

"That's cool. What's that any_cast do? I didn't know any_cast was a C++ keyword, but it must be a keyword because it isn't qualified by boost::...?"

"No, it is a free function template. It makes its home in the boost namespace, but because the object we pass it is also from namespace boost, compilers that correctly implement Koenig lookup — alas, not all do — will find the function correctly even without a using-declaration or explicit qualification. The any_cast is intended to be analogous to the already-blessed dynamic_cast. It will attempt to convert the given operand into the type requested. If the conversion is possible, the cast returns the original object converted to the desired type. If not, then the cast returns a null pointer if the operand was a pointer or throws an exception if the operand was a reference or object."

I was impressed. "Well, it looks easy enough to copy any objects and extract the values, but in that code you knew the value you wanted the any object to hold at the time you created it. What if you don't know the value until later? Do you have to construct another any helper and then assign from it like that?"

"No, my child." In the near distance, I noticed Bob's head appear partially around a cubicle divider, shake disgustedly at these words, and disappear again. The Guru smiled enigmatically. "The any class provides a templated assignment operator, allowing you to easily write code such as:"

{
 boost::any holdsAnything; 
 holdsAnything = 9;
 holdsAnything = std::string("Hello, world");
 holdsAnything = 3.1415926;
}

"You will also note," the Guru continued, "that the any class supports null or empty semantics, which is to say, the value type currently holds no value. Further, to facilitate extracting the value, the any class provides a type function, which returns a std::type_info class, indicating the type of value currently held in the any class."

"Say," I barged in. "I just thought of something — this would be a great way to implement properties. Just create a struct that has a std::string for the property name, and an any class for the property value."

"Indeed, my young apprentice," the Guru nodded. "The prophet Henney suggests properties as one potential use of any [2]. For an any could hold anything. And it could lead anywhere..."

"What? How do you mean?"

"Because," she explained, "another possibility is to use an any class as the parameter for polymorphic-based callbacks. As I recall, the example Henney gives is:"

class consumer
{
public:
 virtual void notify(const any &) = 0;
};

"Ah. Well, anyway," I grinned, "thanks for providing me the piece of the puzzle I needed." The Guru bowed her head, reopened her tome, and glided silently away as I turned back to my keyboard.


"Excellent work, excellent, most excellent," Gilb kept repeating. "Unusual, most unusual. What about the artifacts? Has there been more progress? Have we found anything new to defend ourselves?"

That irked me. "Major," I blurted, "we have no idea what this is or what it means. I know our situation, but there's much more to this than weapons! We've already performed one test and —"

"You forget yourself," the major cut me off. It was the first time he had done that, and I stopped. Then, resuming his usual cajoling voice, he continued: "We're all under stress. We haven't much time, no time at all. This test, what was it, what did you do?"

"A pole," Jeannine responded. "We took a long pole and put it against the ball. It entered, without resistance, and we could see it leave a mark on the beach. We pushed the pole in further than the ball is wide, and it didn't come out the other side of the ball here. It's still there," she gestured and moved to show him, and we shifted to follow her. "It's as if that beach was right there, within arm's reach. I haven't tried, but I'm sure I could touch it. The ball is like a hole in the universe."

Gilb took in this information, then moved to the grassy scene, and then to the metallic room scene.

Just then, as we circled the metallic room to look out at it from different directions, something new came into view. A man dressed in an oddly cut gray costume was standing at one of the cabinets, holding some sort of flat device and manipulating it. Suddenly, as though just aware of us, he turned in our direction and stared. His mouth began moving, and after the briefest pause we heard in English: "Should you be here?"

References

[1] To the tune of "I'd Do Anything," Oliver!, 1968.

[2] C++ Boost any class, Kevlin Henney, <www.boost.org/libs/any/index.html>.


Jim Hyslop is a senior software designer at Leitch Technology International Inc. He can be reached at jim.hyslop@leitch.com.

Herb Sutter is an independent consultant and secretary of the ISO/ANSI C++ standards committee. He is also one of the instructors of The C++ Seminar (<www.gotw.ca/cpp_seminar>). Herb can be reached at hsutter@acm.org.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.