Пазл для мастеров шаблонов - PullRequest
1 голос
/ 28 октября 2010

Я бы хотел сделать следующее:

const int someInt;
const std::vector<int> someIntList;
const std::vector<std::vector<int>> someNestedIntList;

Marshall(someInt); // trivial case
Marshall(someIntList); // difficult case
Marshall(someNestedIntList); // difficult case

Я попробовал следующее:

template<std::vector<class Element>> 
void Marshall(const std::vector<Element>& toBeMarshalled)
{
    for (int i=0; i<toBeMarshalled.size(); ++i)
        Marshall<Element>(toBeMarshalled[i]);
}

К сожалению, это не компилируется, и мне не удалось найти правильный синтаксис для него.

Обратите внимание, что должен быть только один параметр шаблона, иначе сортировка вложенного списка не будет работать.

Обновление : Благодаря ответу FredOverflow я нашел то, что искал. Я забыл, что у всех контейнерных классов в стандартной библиотеке есть value_type typedef. Это может быть использовано в качестве обходного пути для моей проблемы:

template <class Container> 
void Marshall(const Container& toBeMarshalled)
{
    for (UINT32 i=0; i<toBeMarshalled.size(); ++i)
        Marshall<Container::value_type>(toBeMarshalled);
}

Это немного патч, но я думаю, что он достаточно хорош.

Ответы [ 4 ]

7 голосов
/ 28 октября 2010

С вашим шаблоном не так:

  1. Объявление шаблона неверно. Здесь перечислены только аргументы шаблона, а не типы аргументов функции. Кроме того, >> анализируется как оператор сдвига.
  2. std::vector имеет два параметра шаблона. Хотя в вашей повседневной работе вы редко будете использовать вторую, она все еще там и должна быть в списке, иначе ваш шаблон потерпит неудачу, если кто-нибудь попытается использовать его с std::vector, который не использует распределитель по умолчанию.

Это должно работать для всех std::vector экземпляров:

template< typename T > 
void Marshall(const T& toBeMarshalled)
{
  // ...
}

template< typename T, class A > 
void Marshall(const std::vector<T,A>& toBeMarshalled)
{
    for (typename std::vector<T,A>::size_type i=0; i<toBeMarshalled.size(); ++i)
        Marshall(toBeMarshalled[i]);
}
4 голосов
/ 28 октября 2010

Объявление шаблона неверно. Есть:

template< class Element >
void marshall( std::vector< Element > const& v )

Приветствия и hth.,

3 голосов
/ 28 октября 2010

Могу ли я предложить SFINAE и некоторое ускоренное метапрограммирование?

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

template <class T>
struct has_begin_end
{
    template <class U,
              typename U::const_iterator (U::*)() const,
              typename U::const_iterator (U::*)() const>
    struct sfinae { };

    template <class U>
    static char test(sfinae<U, &U::begin, &U::end>*);

    template <class>
    static long test(...);

    enum { value = (1 == sizeof test<T>(0)) };
    typedef boost::integral_constant<bool, value> type;
};

template <class Value>
typename boost::disable_if<has_begin_end<Value>, void>::type
Marshall(const Value& value)
{
    std::cout << value << ' ';
}

template <class Container>
typename boost::enable_if<has_begin_end<Container>, void>::type
Marshall(const Container& c)
{
    std::for_each(c.begin(), c.end(), Marshall<typename Container::value_type>);
}

int main()
{
    const int someInt = 42;
    const std::vector<int> someIntList {2, 3, 5, 7};
    const std::vector<std::vector<int>> someNestedIntList {{11, 13}, {17, 19}};

    Marshall(someInt);
    Marshall(someIntList);
    Marshall(someNestedIntList);
}
2 голосов
/ 28 октября 2010

Код, который вы вставили, содержит >> в конце объявления шаблона.Компиляторы C ++ будут интерпретировать это не как две закрывающие угловые скобки, а как один оператор смещения вправо.

Попробуйте template<std::vector<class Element> > с пробелом между скобками.

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