Лямбды не могут быть построены по умолчанию. Итак, вам нужно передать операторы хеширования / равенства. В качестве альтернативы вы можете получить именованный тип лямбды и добавить конструктивность по умолчанию:
Простейшим было бы объединить ha sh соответственно операции равенства для двойных / тройных кортежей:
struct HashTuple {
template <typename T, typename U>
auto operator()(const std::tuple<T, U>& singleTuple) const -> size_t
{
size_t seed{};
hash_combine(seed, hash_value(std::get<0>(singleTuple)));
hash_combine(seed, hash_value(std::get<1>(singleTuple)));
return seed;
}
template <typename T, typename U, typename D>
auto operator()(const std::tuple<T, U, D>& singleTuple) const -> size_t
{
size_t seed{};
hash_combine(seed, hash_value(std::get<0>(singleTuple)));
hash_combine(seed, hash_value(std::get<1>(singleTuple)));
hash_combine(seed, hash_value(std::get<2>(singleTuple)));
return seed;
}
};
struct EqualTuple {
template <typename... T>
auto operator()(const std::tuple<T...>& firstTuple, const std::tuple<T...>& secondTuple) const -> bool {
return firstTuple == secondTuple;
}
};
Обратите внимание, что здесь используется эквивалентная std::tuple::operator==
реализация
Теперь вы можете упростить типы:
std::unordered_map<std::tuple<double, int, double>, int, HashTuple, EqualTuple>
std::unordered_map<std::tuple<unsigned int, int>, int, HashTuple, EqualTuple>
Что я бы резюмировал с помощью простого помощника:
template <typename... Key> using FrequencyMap =
std::unordered_map<std::tuple<Key...>, InstrumentFrequency, HashTuple, EqualTuple>;
using FutureTupleUnorderedMap = FrequencyMap<TotalDelta, Instrument::InstrumentID, Platform::Price>;
using OptionTupleUnorderedMap = FrequencyMap<Platform::Quantity, Instrument::InstrumentID>;
Теперь у нас есть полностью рабочая демонстрация:
Live On Coliru
#include <boost/functional/hash.hpp>
#include <tuple>
#include <unordered_map>
struct Instrument {
using InstrumentID = int;
};
struct Platform {
using Quantity = unsigned;
using Price = double;
};
namespace Valk::ExchangeGateway::TupleMap {
struct HashTuple {
template <typename T, typename U>
auto operator()(const std::tuple<T, U>& singleTuple) const -> size_t
{
using boost::hash_value;
using boost::hash_combine;
size_t seed{};
hash_combine(seed, hash_value(std::get<0>(singleTuple)));
hash_combine(seed, hash_value(std::get<1>(singleTuple)));
return seed;
}
template <typename T, typename U, typename D>
auto operator()(const std::tuple<T, U, D>& singleTuple) const -> size_t
{
using boost::hash_value;
using boost::hash_combine;
size_t seed{};
hash_combine(seed, hash_value(std::get<0>(singleTuple)));
hash_combine(seed, hash_value(std::get<1>(singleTuple)));
hash_combine(seed, hash_value(std::get<2>(singleTuple)));
return seed;
}
};
struct EqualTuple {
template <typename... T>
auto operator()(const std::tuple<T...>& firstTuple, const std::tuple<T...>& secondTuple) const -> bool {
return firstTuple == secondTuple;
}
};
using InstrumentFrequency = int;
using TotalDelta = double;
template <typename... Key> using FrequencyMap =
std::unordered_map<std::tuple<Key...>, InstrumentFrequency, HashTuple, EqualTuple>;
using FutureTupleUnorderedMap = FrequencyMap<TotalDelta, Instrument::InstrumentID, Platform::Price>;
using OptionTupleUnorderedMap = FrequencyMap<Platform::Quantity, Instrument::InstrumentID>;
}
#include <boost/core/demangle.hpp>
#include <iostream>
int main() {
{
Valk::ExchangeGateway::TupleMap::FutureTupleUnorderedMap ftum;
std::cout << boost::core::demangle(typeid(ftum).name()) << "\n";
}
{
Valk::ExchangeGateway::TupleMap::OptionTupleUnorderedMap otum;
std::cout << boost::core::demangle(typeid(otum).name()) << "\n";
}
}
Печатает имена типов вы видели выше.