Click here to Skip to main content
11,925,006 members (53,584 online)
Click here to Skip to main content
Add your own
alternative version


75 bookmarked

High Performance Dynamic Typing in C++ using a Replacement for boost::any

, 9 May 2011 CPOL
Rate this:
Please Sign up or sign in to vote.
A high-performance alternative to boost::any.


The Boost library provides a very useful little class called boost::any which can contain a value of virtually any type as long as that value supports copy construction and assignment. This boost::any type allows dynamic querying of the contained type, and safe type conversions. Despite its usefulness, boost::any is not as efficient as it could be, so I have rewritten my own, which I have immodestly called cdiggins::any.

Updated in 2011: After five years, I have rewritten the class from scratch to fix some really nasty bugs and to simplify the code.

Using cdiggins::any

The cdiggins::any type can be used to hold normal value types, and provides a mechanism to safely and explicitly cast back to the appropriate type.

any a = 42;
cout << a.cast<int>() << endl;
a = 13;
cout << a.cast<int>() << endl;
a = "hello";
cout << a.cast<const char*>() << endl;
a = std::string("1234567890");
cout << a.cast<std::string>() << endl;
int n = 42;
a = &n;
cout << *a.cast<int*>() << endl;
any b = true;
cout << b.cast<bool>() << endl;
swap(a, b);        
cout << a.cast<bool>() << endl;
a.cast<bool>() = false;
cout << a.cast<bool>() << endl;

Design of cdiggins::any

The cdiggins::any class contains two pointers: one to a policy class (any::policy) and one is a pointer to the data (any::data) which may in certain cases be used to contain the data itself (for example, if storing a primitive data type smaller than or equal to the size of a pointer).

The policy class is used for performing allocations, deallocation, copies, etc., and determines whether to use any::data to hold the data or point to the data.

Finally, without further ado, here is the implementation of the cdiggins::any class for your enjoyment:

#pragma once
 * (C) Copyright Christopher Diggins 2005-2011
 * (C) Copyright Pablo Aguilar 2005
 * (C) Copyright Kevlin Henney 2001
 * Distributed under the Boost Software License, Version 1.0. (See
 * accompanying file LICENSE_1_0.txt or copy at

#include <stdexcept>

namespace cdiggins
namespace anyimpl
    struct bad_any_cast 

    struct empty_any 

    struct base_any_policy 
        virtual void static_delete(void** x) = 0;
        virtual void copy_from_value(void const* src, void** dest) = 0;
        virtual void clone(void* const* src, void** dest) = 0;
        virtual void move(void* const* src, void** dest) = 0;
        virtual void* get_value(void** src) = 0;
        virtual size_t get_size() = 0;

    template<typename T>
    struct typed_base_any_policy : base_any_policy
        virtual size_t get_size() { return sizeof(T); } 

    template<typename T>
    struct small_any_policy : typed_base_any_policy<T>
        virtual void static_delete(void** x) { }
        virtual void copy_from_value(void const* src, void** dest)
            { new(dest) T(*reinterpret_cast<T const*>(src)); }
        virtual void clone(void* const* src, void** dest) { *dest = *src; }
        virtual void move(void* const* src, void** dest) { *dest = *src; }
        virtual void* get_value(void** src) { return reinterpret_cast<void*>(src); }

    template<typename T>
    struct big_any_policy : typed_base_any_policy<T>
        virtual void static_delete(void** x) { if (*x) 
            delete(*reinterpret_cast<T**>(x)); *x = NULL; }
        virtual void copy_from_value(void const* src, void** dest) { 
           *dest = new T(*reinterpret_cast<T const*>(src)); }
        virtual void clone(void* const* src, void** dest) { 
           *dest = new T(**reinterpret_cast<T* const*>(src)); }
        virtual void move(void* const* src, void** dest) { 
          **reinterpret_cast<T**>(dest) = **reinterpret_cast<T* const*>(src); }
        virtual void* get_value(void** src) { return *src; }

    template<typename T>
    struct choose_policy 
        typedef big_any_policy<T> type;

    template<typename T> 
    struct choose_policy<T*> 
        typedef small_any_policy<T*> type; 
    struct any;

    /// Choosing the policy for an any type is illegal, but should never happen.
    /// This is designed to throw a compiler error.
    struct choose_policy<any>
        typedef void type;

    /// Specializations for small types.
    #define SMALL_POLICY(TYPE) template<> struct 
       choose_policy<TYPE> { typedef small_any_policy<TYPE> type; };

    SMALL_POLICY(signed char);
    SMALL_POLICY(unsigned char);
    SMALL_POLICY(signed short);
    SMALL_POLICY(unsigned short);
    SMALL_POLICY(signed int);
    SMALL_POLICY(unsigned int);
    SMALL_POLICY(signed long);
    SMALL_POLICY(unsigned long);

    #undef SMALL_POLICY

    /// This function will return a different policy for each type. 
    template<typename T>
    base_any_policy* get_policy()
        static typename choose_policy<T>::type policy;
        return &policy;

struct any
    // fields
    anyimpl::base_any_policy* policy;
    void* object;

    /// Initializing constructor.
    template <typename T>
    any(const T& x) 
        : policy(anyimpl::get_policy<anyimpl::empty_any>()), object(NULL) 

    /// Empty constructor. 
        : policy(anyimpl::get_policy<anyimpl::empty_any>()), object(NULL) 
    { }

    /// Special initializing constructor for string literals. 
    any(const char* x) 
        : policy(anyimpl::get_policy<anyimpl::empty_any>()), object(NULL) 

    /// Copy constructor. 
    any(const any& x) 
        : policy(anyimpl::get_policy<anyimpl::empty_any>()), object(NULL)         

    /// Destructor. 
    ~any() {

    /// Assignment function from another any. 
    any& assign(const any& x) {
        policy = x.policy;
        policy->clone(&x.object, &object);
        return *this;

    /// Assignment function. 
    template <typename T>
    any& assign(const T& x) {
        policy = anyimpl::get_policy<T>();
        policy->copy_from_value(&x, &object);
        return *this;

    /// Assignment operator.
    template<typename T>
    any& operator=(const T& x) {
        return assign(x);

    /// Assignment operator, specialed for literal strings. 
    /// They have types like const char [6] which don't work as expected. 
    any& operator=(const char* x) {
        return assign(x);

    /// Utility functions
    any& swap(any& x) {
        std::swap(policy, x.policy);
        std::swap(object, x.object);
        return *this;

    /// Cast operator. You can only cast to the original type.
    template<typename T>
    T& cast() {
        if (policy != anyimpl::get_policy<T>()) 
            throw anyimpl::bad_any_cast();
        T* r = reinterpret_cast<T*>(policy->get_value(&object)); 
        return *r;

    /// Returns true if the any contains no value. 
    bool empty() const {
        return policy == anyimpl::get_policy<anyimpl::empty_any>();

    /// Frees any allocated memory, and sets the value to NULL.
    void reset() {
        policy = anyimpl::get_policy<anyimpl::empty_any>();

    /// Returns true if the two types are the same. 
    bool compatible(const any& x) const {
        return policy == x.policy;

Final Words

Thanks to Pablo Aguilar who helped with an early version of the cdiggins::any class. Thanks to Raute who helped me identify the critical problems in the original version of cdiggins::any.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Christopher Diggins
Software Developer Autodesk
Canada Canada
This article was written by Christopher Diggins, a computer science nerd who currently works at Autodesk as an SDK specialist.

You may also be interested in...

Comments and Discussions

QuestionImplicit cast fix Pin
Member 1154432525-Mar-15 12:59
memberMember 1154432525-Mar-15 12:59 
QuestionLast version still buggy (but I don't have a solution) Pin
David O'Neil4-Oct-14 12:45
memberDavid O'Neil4-Oct-14 12:45 
QuestionPlease someone add Move constructor Pin
jeefo124-May-14 17:54
memberjeefo124-May-14 17:54 
Questionnot working with "unsigned int" Pin
cristi.arghiroiu19-Feb-14 2:00
membercristi.arghiroiu19-Feb-14 2:00 
Questionfix the const problem Pin
pj220_20068-Aug-13 23:12
memberpj220_20068-Aug-13 23:12 
AnswerRe: fix the const problem Pin
skyformat99@gmail.com31-Jan-14 22:47
memberskyformat99@gmail.com31-Jan-14 22:47 
AnswerRe: fix the const problem Pin
David O'Neil28-Feb-14 21:23
memberDavid O'Neil28-Feb-14 21:23 
QuestionBugfix Pin
David O'Neil9-Jul-13 21:45
memberDavid O'Neil9-Jul-13 21:45 
QuestionAn overlooked usage case in new code Pin
David O'Neil26-Jan-13 20:01
memberDavid O'Neil26-Jan-13 20:01 
QuestionA small helper function for you Pin
David O'Neil24-Jan-13 18:53
memberDavid O'Neil24-Jan-13 18:53 
I just updated my projects to use your new code. First, congratulations on the changes - this updated version is SO much cleaner than the original I can almost wrap my head around it! But I was missing the 'type' function of your old version, as my main project using this tested against that. So I came up with the following small addition which makes replacing that functionality much easier.
template<typename T>
bool compatible() {
  T temp;
  return compatible(temp);
Just add this under the definition of the other 'compatible' function. For those readers who try to use it and are unfamiliar with the template terminology, an example invocation would be something like
if (!buttonC->user.compatible<int>()) doSomething();
Pretty simple, and not much of an addition, but hopefully helpful to some.

[Edit] Having used this for an hour, I'm changing 'compatible' to 'isA', as it better describes the usage context. For example,
if (!buttonC->user.isA<int>()) doSomething();
is a richer and more meaningful syntax than the original.

modified 25-Jan-13 1:32am.

Questionerror: 'TYPE' was not declared in this scope Pin
yurenjimi198520-Nov-12 16:44
memberyurenjimi198520-Nov-12 16:44 
AnswerRe: error: 'TYPE' was not declared in this scope Pin
Member 968039912-Dec-12 13:10
memberMember 968039912-Dec-12 13:10 
GeneralIt looks good, but is that dynamic typing? Pin
Jamming114-May-11 13:20
memberJamming114-May-11 13:20 
GeneralRe: It looks good, but is that dynamic typing? Pin
MetaVoid29-Sep-11 10:46
memberMetaVoid29-Sep-11 10:46 
GeneralRe: It looks good, but is that dynamic typing? Pin
jcmalek30-Jan-15 6:49
memberjcmalek30-Jan-15 6:49 
GeneralMemory Leaks and Crashes when storing "non-primitiv" data! Pin
Raute11-Aug-10 4:57
memberRaute11-Aug-10 4:57 
GeneralRe: Memory Leaks and Crashes when storing "non-primitiv" data! Pin
Christopher Diggins9-May-11 16:31
memberChristopher Diggins9-May-11 16:31 
GeneralQuestion on checking empty Pin
Member 421168429-Mar-10 10:26
memberMember 421168429-Mar-10 10:26 
GeneralPreventing Reallocations Pin
Anand Krishnamoorthi18-Apr-07 7:15
memberAnand Krishnamoorthi18-Apr-07 7:15 
QuestionSmall Types Assignment Problem? Pin
Anand Krishnamoorthi18-Apr-07 7:10
memberAnand Krishnamoorthi18-Apr-07 7:10 
AnswerRe: Small Types Assignment Problem? Pin
xryl6695-Sep-07 3:28
memberxryl6695-Sep-07 3:28 
GeneralCompile problem with cast Pin
Neville Franks17-Jul-06 14:15
memberNeville Franks17-Jul-06 14:15 
GeneralRe: Compile problem with cast Pin
pablo_mag17-Jul-06 15:00
memberpablo_mag17-Jul-06 15:00 
GeneralRe: Compile problem with cast [modified] Pin
Neville Franks17-Jul-06 15:31
memberNeville Franks17-Jul-06 15:31 
GeneralRe: Compile problem with cast [modified] Pin
pablo_mag17-Jul-06 16:55
memberpablo_mag17-Jul-06 16:55 
GeneralRe: Compile problem with cast Pin
Neville Franks17-Jul-06 19:53
memberNeville Franks17-Jul-06 19:53 
GeneralCompile error with const char* Pin
farshizzo26-Apr-06 8:23
memberfarshizzo26-Apr-06 8:23 
GeneralRe: Compile error with const char* Pin
pablo_mag17-Jul-06 14:47
memberpablo_mag17-Jul-06 14:47 
GeneralUpdate Posted Pin
pablo_mag18-Sep-05 23:06
memberpablo_mag18-Sep-05 23:06 
GeneralRe: Update Posted Pin
Christopher Diggins19-Sep-05 4:58
memberChristopher Diggins19-Sep-05 4:58 
GeneralRe: Update Posted Pin
David O'Neil21-Sep-05 8:31
memberDavid O'Neil21-Sep-05 8:31 
GeneralRe: Update Posted Pin
pablo_mag21-Sep-05 8:33
memberpablo_mag21-Sep-05 8:33 
GeneralRe: Update Posted Pin
Temp8316-Feb-06 7:03
memberTemp8316-Feb-06 7:03 
GeneralRe: Update Posted Pin
pablo_mag16-Feb-06 7:18
memberpablo_mag16-Feb-06 7:18 
GeneralRe: Update Posted Pin
Temp8317-Feb-06 3:34
memberTemp8317-Feb-06 3:34 
GeneralRe: Update Posted Pin
pablo_mag17-Feb-06 12:36
memberpablo_mag17-Feb-06 12:36 
GeneralRe: Update Posted Pin
Temp8318-Feb-06 7:26
memberTemp8318-Feb-06 7:26 
GeneralRe: Update Posted Pin
pablo_mag18-Feb-06 11:31
memberpablo_mag18-Feb-06 11:31 
GeneralRe: Update Posted Pin
Temp8321-Feb-06 8:07
memberTemp8321-Feb-06 8:07 
GeneralRe: Update Posted Pin
pablo_mag21-Feb-06 8:14
memberpablo_mag21-Feb-06 8:14 
GeneralTrouble with classes with 'any' members used in vectors Pin
David O'Neil12-Sep-05 8:42
memberDavid O'Neil12-Sep-05 8:42 
GeneralRe: Trouble with classes with 'any' members used in vectors Pin
pablo_mag16-Sep-05 13:05
memberpablo_mag16-Sep-05 13:05 
GeneralRe: Trouble with classes with 'any' members used in vectors Pin
David O'Neil16-Sep-05 15:48
memberDavid O'Neil16-Sep-05 15:48 
Questionwhy using any_detail::get_table&lt;any_detail::empty&gt;::get();? Pin
gunnar6719-Aug-05 10:31
membergunnar6719-Aug-05 10:31 
AnswerRe: why using any_detail::get_table&lt;any_detail::empty&gt;::get();? Pin
Christopher Diggins19-Aug-05 12:07
memberChristopher Diggins19-Aug-05 12:07 
QuestionIsn't there a possible leak? Pin
gunnar6719-Aug-05 9:20
membergunnar6719-Aug-05 9:20 
AnswerRe: Isn't there a possible leak? Pin
Christopher Diggins19-Aug-05 9:26
memberChristopher Diggins19-Aug-05 9:26 
GeneralDownload of source file is broken Pin
Anonymous9-Aug-05 9:18
sussAnonymous9-Aug-05 9:18 
GeneralRe: Download of source file is broken Pin
Christopher Diggins9-Aug-05 9:24
memberChristopher Diggins9-Aug-05 9:24 
GeneralRe: Download of source file is broken Pin
Christopher Diggins9-Aug-05 10:11
memberChristopher Diggins9-Aug-05 10:11 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.151125.3 | Last Updated 9 May 2011
Article Copyright 2005 by Christopher Diggins
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid