tags:

views:

41

answers:

2

I am trying to implement a free operator function in order to stream values of arbitrary data type into some container class (DataVector).
I did a template for basic data types and some specializations for the complex data types used in my project (examples covers std::string only).
To make sure the template won't be used with a data type which is not properly handled by the basic implementation, I want to restrict instatiation using type traits (is_integral). Several attempts embedding is_enabled is_integral into the signature of the operator failed and I ended up with the implementation show in the example below.

typedef std::vector<unsigned char> DataVector;

template<typename T>
DataVector& operator <<(DataVector& vecArchive, T dataToAppend)
{
    if (boost::is_integral<T>::value == true)
    {
        // ... do something
        return vecArchive;
    }
    BOOST_STATIC_ASSERT(false);
};

template<> inline
DataVector& operator << <string> (DataVector& vecArchive, string dataToAppend)
{
    // do something different
    return vecArchive;
};

The problem is that it won't compile, even for integral data types. I guess BOOST_STATIC_ASSERT cannot be used in conditional expressions. How can it be done? Any help would be greatly appreciated.

main()
{
    DataVector vecTel;
    vecTel << (int)5;  // ok
    vecTel << std::string("Hello World");  // ok
    vecTel << std::map(int, int)  // must fail
}

Compiler error:

d:...\TcpSerializable.h(52) : error C2027: use of undefined type 'boost::STATIC_ASSERTION_FAILURE' with [ x=false ] .\Telegram050.cpp(38) : see reference to function template instantiation 'BasisKlassen::DataVector &BasisKlassen::operator <<(BasisKlassen::DataVector &,T)' being compiled with [ T=int ]

+2  A: 

I am no expert on boost, but from the look of it BOOST_STATIC_ASSERT(0) will compile even if the boost::is_integral<T>::value returns true (similar all other normal functions). Hence you get the compiler error (as intended when static assert's condition returns false). To fix this, the simplest would be change the the function to something like:

template<typename T>
DataVector& operator <<(DataVector& vecArchive, T dataToAppend)
{
    BOOST_STATIC_ASSERT(boost::is_integral<T>::value);
    // ... do something
    return vecArchive;

};
Naveen
+2  A: 

You could use boost's enable_if, if you really need to restrict a certain implementation to integral types:

#include <boost/type_traits.hpp>
#include <boost/utility.hpp>

// operator<< for integral types
template<typename T>
typename boost::enable_if< boost::is_integral<T>, DataVector& >::type
operator<<(DataVector& vecArchive, T dataToAppend) {
    // ... do something
    return vecArchive;
};

// different operator<< for std::string
DataVector& operator<<(DataVector &vecArchive, const std::string &dataToAppend) {
    return vecArchive;
}

If you try to use this with a non-integral type you get the usual compiler error that no matching operator<< was found.

sth
Thanks for the answer. This is the way I tried it before, but like this somehow the specializations won't compile anymore. Error C2912: explicit specialization; ... is not a specialization of a function template
raines
@raines: Probably since this template "only exists" for integral types, there is nothing to be specialized for other types. But you are probably anyway better of by using simple overloads (like I edited into my answer) instead of template specializations for those other types. If you just create new overloaded functions/templates for the `operator<<` for other types it should be resolved correctly. (See also [here](http://www.gotw.ca/publications/mill17.htm) for more details)
sth