Reputation: 317
I have multi index container like below
typedef Lock_<boost::mutex> DefaultLock;
template<class ADD_DATA>
struct ResourceRawData : private boost::noncopyable
{
ResourceRawData(const TSTRING& pathFileName,bool bMustDirectory,const ADD_DATA& addData = ADD_DATA() )
{
...
}
ResourceRawData(const TSTRING& pathFileName,const TSTRING& strSettingName,bool bMustDirectory,const ADD_DATA& addData = ADD_DATA() )
{
...
}
}
template<class ADD_DATA>
class ResourceQueue : public DefaultLock , private boost::noncopyable
{
typedef typename ResourceRawData< ADD_DATA > QUEUE_DATA;
typedef typename boost::shared_ptr< QUEUE_DATA > SP_QUEUE_DATA;
typedef boost::multi_index_container<
SP_QUEUE_DATA,
boost::multi_index::indexed_by<
boost::multi_index::sequenced<>,
boost::multi_index::hashed_unique< BOOST_MULTI_INDEX_CONST_MEM_FUN(QUEUE_DATA,const TSTRING&,GetFileName),string_hash >
>
> MULTI_INDEX_QUEUE;
typedef typename MULTI_INDEX_QUEUE::nth_index<0>::type QUEUE_INDEX_SEQUENCE; << error C2059: syntax error: '<'
typedef typename MULTI_INDEX_QUEUE::nth_index<1>::type QUEUE_INDEX_MAP;
}
error detail:
(322,47): error C2059: syntax error: '<'
(330): message : see reference to class template instantiation 'ResourceQueue<ADD_DATA>' being compiled
above code is compiled fine with visual studio 2008, but not with visual studio 2019, am I missing something? any usage standard changes with boost if I use with visual studio 2019?
thanks for help
Upvotes: 1
Views: 75
Reputation: 392903
Two-phase lookup was recently fixed in MSVC. You might now run into a diagnostic that this use of typename
was actually non-conformant (should never have compiled):
typedef typename ResourceRawData< ADD_DATA > QUEUE_DATA;
Just remove it
typedef ResourceRawData< ADD_DATA > QUEUE_DATA;
very similarly, the compiler will no longer wrongly accept unqualified template members on dependent types:
typedef typename MULTI_INDEX_QUEUE::nth_index<0>::type QUEUE_INDEX_SEQUENCE;
You need to add template
before the nested nth_index
:
typedef typename MULTI_INDEX_QUEUE::template nth_index<0>::type QUEUE_INDEX_SEQUENCE;
typedef typename MULTI_INDEX_QUEUE::template nth_index<1>::type QUEUE_INDEX_MAP;
Now it compiles: GCC.
Now consider using type deduction to simplify a lot of the code:
MULTI_INDEX_QUEUE _queue;
auto& index_sequence() { return _queue.template get<0>(); }
auto& index_map() { return _queue.template get<1>(); }
Modernizing things and mocking some of the things left out:
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/mem_fun.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/thread.hpp>
using TSTRING = std::string;
using string_hash = boost::hash<TSTRING>;
// no idea really, just making this up:
template <typename M> struct Lock_ : boost::unique_lock<M> {
Lock_() : boost::unique_lock<M>(_mx, boost::defer_lock) {}
M _mx;
};
using DefaultLock = Lock_<boost::mutex>;
template <class ADD_DATA> struct ResourceRawData : private boost::noncopyable
{
ResourceRawData(const TSTRING & pathFileName, bool /*bMustDirectory*/,
const ADD_DATA & addData = ADD_DATA())
: _name(pathFileName), _value(addData) { }
TSTRING const &GetFileName() const { return _name; }
ADD_DATA const &GetValue() const { return _value; }
private:
TSTRING _name;
ADD_DATA _value;
};
namespace bmi = boost::multi_index;
template <class ADD_DATA>
class ResourceQueue : public DefaultLock, private boost::noncopyable
{
using QUEUE_DATA = ResourceRawData<ADD_DATA>;
using SP_QUEUE_DATA = boost::shared_ptr<QUEUE_DATA>;
using MULTI_INDEX_QUEUE = bmi::multi_index_container<SP_QUEUE_DATA,
bmi::indexed_by<
bmi::sequenced<>,
bmi::hashed_unique<
::bmi::const_mem_fun<QUEUE_DATA, const TSTRING &, &QUEUE_DATA::GetFileName>,
string_hash>
>
>;
MULTI_INDEX_QUEUE _queue;
auto& index_map() { return _queue.template get<1>(); }
auto const& index_map() const { return _queue.template get<1>(); }
public:
auto& index_sequence() { return _queue.template get<0>(); }
auto const& index_sequence() const { return _queue.template get<0>(); }
bool insert(TSTRING fname, ADD_DATA value)
{
return index_sequence()
.push_back(
boost::make_shared<QUEUE_DATA>(std::move(fname), false, value))
.second;
}
ADD_DATA ValueByPath(TSTRING const &key) const
{
if (auto it = index_map().find(key); it != index_map().end())
{
return (*it)->GetValue();
}
else
{
return ADD_DATA{};
}
}
};
#include <iostream>
int main() {
ResourceQueue<int> rq;
assert(rq.insert("aaaa", 99));
assert(rq.insert("bbbb", 42));
assert(not rq.insert("aaaa", -1)); // not unique!
assert(rq.insert("cccc", 100));
std::cout << "index_sequence:\n";
for (auto const &p : rq.index_sequence())
{
std::cout << p->GetFileName() << " -> " << p->GetValue() << "\n";
}
std::cout << "\nindex_map: " << rq.ValueByPath("bbbb") << "\n";
}
Prints
index_sequence:
aaaa -> 99
bbbb -> 42
cccc -> 100
index_map: 42
Upvotes: 1