Ограничение создания шаблона с помощью is_integral / BOOST_STATIC_ASSERT - PullRequest
1 голос
/ 28 сентября 2010

Я пытаюсь реализовать функцию свободного оператора для потоковой передачи значений произвольного типа данных в некоторый контейнерный класс (DataVector).
Я сделал шаблон для базовых типов данных и некоторых специализаций для сложных типов данных, используемых в моем проекте (примеры охватывают только std :: string).
Чтобы убедиться, что шаблон не будет использоваться с типом данных, который неправильно обрабатывается базовой реализацией, я хочу ограничить инсталяцию с помощью признаков типа (is_integral). Несколько попыток встраивания is_enabled is_integral в сигнатуру оператора потерпели неудачу, и я закончил с реализацией, показанной в примере ниже.

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;
};

Проблема в том, что он не будет компилироваться даже для целочисленных типов данных. Я предполагаю, что BOOST_STATIC_ASSERT нельзя использовать в условных выражениях. Как это можно сделать? Любая помощь будет принята с благодарностью.

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

Ошибка компилятора:

d: ... \ TcpSerializable.h (52): ошибка C2027: использование неопределенного типа 'boost :: STATIC_ASSERTION_FAILURE' с [ х = ложно ] . \ Telegram050.cpp (38): см. Ссылку на компилируемую реализацию шаблона функции 'BasisKlassen :: DataVector & BasisKlassen :: operator << (BasisKlassen :: DataVector &, T)' с [ Т = INT ] </p>

Ответы [ 2 ]

4 голосов
/ 28 сентября 2010

Я не эксперт по boost, но, судя по всему, BOOST_STATIC_ASSERT(0) скомпилируется, даже если boost::is_integral<T>::value вернет true (аналогично всем другим нормальным функциям).Следовательно, вы получаете ошибку компилятора (как и предполагалось, когда статическое условие assert возвращает false).Чтобы это исправить, проще всего изменить функцию на что-то вроде:

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

};
3 голосов
/ 28 сентября 2010

Вы можете использовать boost enable_if, если вам действительно нужно ограничить определенную реализацию целочисленными типами:

#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;
}

Если вы попытаетесь использовать это с нецелымтипа вы получаете обычную ошибку компилятора, что не найдено совпадений operator<<.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...