Помеченный 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;
(нет необходимости определять их). Смотрите это в прямом эфире