Помеченный Boost:: BIMAP в шаблонах - они работают?

Я встраиваю boost::bimap в шаблонный класс, и после долгих проб и ошибок я обнаружил то, что компилируется, а что нет. Я использую g++ (GCC) 4.9.2 20150212 (Red Hat 4.9.2-6) и Boost 1.55. Я приведу полный код в Примере 1 и только измененные части для Примера 2 и Примера 3. Функция не делает ничего полезного, только тестируя здесь синтаксис и компилятор.

Пример 1, который выполняет компиляцию (полный список):

#include <string>
#include <boost/bimap/bimap.hpp>
#include <boost/bimap/set_of.hpp>
#include <boost/bimap/unordered_set_of.hpp>
#include <boost/bimap/tags/tagged.hpp>

typedef double Address;

  struct Label1 {};
  struct Label2 {};

template< class TemplateParameter >
class Test
{
 private:

  typedef boost::bimaps::tagged< std::string, Label1 >  KeyType;
  typedef boost::bimaps::tagged< Address, Label2 > ValueType;

// No changes after this line in Example 2 or Example 3

  typedef boost::bimaps::unordered_set_of< KeyType > KeySet;
  typedef boost::bimaps::set_of< ValueType > ValueSet;

  typedef boost::bimaps::bimap < KeySet, ValueSet > BidirectionalMap;

  typedef typename BidirectionalMap::value_type Record;

  // Create the bimap

  BidirectionalMap TheBimap;

  void aFunction ( const Address & AnAddress, 
           const TemplateParameter & Parameters )
  {
    auto NewRecord = TheBimap.insert( Record( "TheGivenAdddress", AnAddress ) );
    auto ByAddress = TheBimap.by< Label1 >().find( "TheGivenAdddress" );
    auto ByNumber = TheBimap.by< Label2 >().find( AnAddress );
  }
};

Я хотел бы инкапсулировать метки внутри класса шаблона, так как нет необходимости, чтобы они были известны за пределами класса. В идеале они должны быть частными, но во избежание проблем с правами доступа они должны быть объявлены как открытые.

Пример 2, который не компилируется (кроме):

typedef double Address;

template< class TemplateParameter >
class Test
{
public:

  struct Label1 {};
  struct Label2 {};

private:

  typedef boost::bimaps::tagged< std::string, Label1 >  KeyType;
  typedef boost::bimaps::tagged< Address, Label2 > ValueType;

Обе строки, к которым метка обращается к bimap, выдают следующее сообщение:

error: expected primary-expression before ‘>’ token
 auto ByAddress = TheBimap.by< Label1 >().find( "TheGivenAdddress" );

Это может быть понято как Label1, который нуждается в полной квалификации, будучи частью шаблонного класса, следующим образом.

auto ByAddress = TheBimap.by< Test<TemplateParameter>::Label1 >().find( "TheGivenAdddress" );

Однако та же самая ошибка произведена. Вопрос 1: Кто-нибудь понимает почему?

Реальная проблема и причина использования класса шаблона Test заключается в том, что я хочу, чтобы тип Label 1 был параметром шаблона. Таким образом, возвращаясь к примеру 1 и только заменяя std::string с параметром шаблона.

Пример 3, который не компилируется (кроме):

typedef double Address;

  struct Label1 {};
  struct Label2 {};

template< class TemplateParameter >
class Test
{
private:

  typedef boost::bimaps::tagged< TemplateParameter, Label1 >  KeyType;
  typedef boost::bimaps::tagged< Address, Label2 > ValueType;

Опять же, обе строки, которые обращаются к карте по тегам, вызывают вышеуказанную ошибку компиляции. Перед тем, как переписать код для использования "левого" и "правого" представлений, было бы хорошо, если бы кто-нибудь мог помочь мне понять Вопрос 2: Почему невозможно использовать параметр шаблона в определении типа тега?

Спасибо за все отзывы!

1 ответ

Решение

Второй случай требует template квалификация. Причина в том, что Label1 а также Label2 теперь зависимые имена.

auto ByAddress = TheBimap.template by<Label1>().find("TheGivenAdddress");
auto ByNumber  = TheBimap.template by<Label2>().find(AnAddress);

См. Где и почему я должен поставить ключевые слова "template" и "typename"?

Вопрос 2: Почему невозможно использовать параметр шаблона в определении тегового типа?

По той же причине. Вам также может понадобиться typename Квалификация там.

демонстрация

Жить на Колиру

#include <string>
#include <boost/bimap/bimap.hpp>
#include <boost/bimap/set_of.hpp>
#include <boost/bimap/unordered_set_of.hpp>
#include <boost/bimap/tags/tagged.hpp>

typedef double Address;

namespace bm = boost::bimaps;

template <class T>
class Test {
  private:
    typedef bm::bimap<
          bm::unordered_set_of<bm::tagged<T,       struct key_idx> >,
          bm::set_of          <bm::tagged<Address, struct value_ix> >
      > BidirectionalMap;

    typedef typename BidirectionalMap::value_type Record;

    BidirectionalMap _theBimap;

  public:
    void aFunction(const Address &anAddress, T const& parameters)
    {
        auto newRecord = _theBimap.insert(Record("TheGivenAdddress", anAddress));
        auto byNumber  = _theBimap.template by<value_ix>().find(anAddress);
        auto byAddress = _theBimap.template by<key_idx>().find(parameters);

        (void) newRecord, (void) byAddress, (void) byNumber;
    }
};

int main() {
    Test<std::string> t;
    t.aFunction(3.14, "hello");
}

Чтобы действительно сохранять типы тегов локальными для класса, добавьте

    struct key_idx;
    struct value_idx;

(нет необходимости определять их). Смотрите это в прямом эфире

Другие вопросы по тегам