Проблема с boost :: tuple в boost :: unordered_map в шаблонном классе

Я написал метод, который автоматически интерполирует дорогую 2D-функцию в C ++. Сейчас я пытаюсь позволить классу принять указатель на функцию, чтобы любая функция могла быть интерполирована. Для этого, похоже, мне нужен шаблонный класс, чтобы я мог шаблонировать его для каждого объекта, для которого он должен оценить указатель функции. Эта часть не так уж плоха после того, как я понял, что мне нужно полностью определить класс в заголовке, чтобы компоновщик мог создать шаблон класса для каждого необходимого объекта. Теперь руб.

В классе я использую boost :: unordered_map для хранения оценок функций, чтобы не вызывать функцию без необходимости. Во время интерполяции я уточняю сетку так, чтобы она достаточно описывала ее (основываясь на ее кривизне). Я локально делю сетку, так что если бы мои исходные точки были в x = 0, .5, 1, следующий набор мог бы быть x = 0, .25, .5, 1, где мне нужно было бы только оценить в х = 0,25 для второго прохода. Это работает само по себе с жестко закодированной функцией вместо указателя динамической функции.

Проблема в том, что я определяю необходимый оператор и функции hash_value для boost :: tuple. Если я помещу это в заголовок, они определяются несколько раз (для каждого включения заголовка). Если я попытаюсь скомпилировать его как объект и связать его, компоновщик не сможет найти определения. Два определения, на которые я должен ссылаться в классе:

bool operator==(const BoostTuple2D &a, const BoostTuple2D &b)
{
return a.tuple.get<0>() == b.tuple.get<0>() &&
a.tuple.get<1>() == b.tuple.get<1>();
}

std::size_t hash_value(const BoostTuple2D &e)
{
std::size_t seed = 0;
boost::hash_combine(seed, e.tuple.get<0>());
boost::hash_combine(seed, e.tuple.get<1>());
return seed;
}

В моем заголовке у меня есть структура и typedef:

struct BoostTuple2D {
BoostTuple2D(double x1, double x2)
: tuple(x1, x2) {}
boost::tuples::tuple<double, double> tuple;
};

typedef boost::unordered_map< BoostTuple2D, double > BoostTuple2DMap;

Который чуть выше моего шаблонного класса, с пропусками:

template<class F>
class Interpolate {
public:
class Evaluate {
// this class uses the map to cache evaluations of the dynamic pointer
}

Interpolate (double (F::*f)(double, double), F & obj, [...]) : f(f), object(obj), ... {};

private:
// members
};

Как я могу сделать методы operator == и hash_value доступными для класса, не определяя их несколько раз? Я охраняю заголовочный файл. Я новичок в C ++, так что, надеюсь, это не так просто. Спасибо!

1

Решение

В случае не шаблонных методов в заголовке, вам нужно будет предшествовать им с ключевым словом «inline». Хотя нет гарантии, что функция будет встроенной (в данном случае это просто подсказка), для нее требуется, чтобы компоновщик допускал несколько определений.

inline bool operator==(const BoostTuple2D &a, const BoostTuple2D &b)
{
return a.tuple.get<0>() == b.tuple.get<0>() &&
a.tuple.get<1>() == b.tuple.get<1>();
}

std::size_t hash_value(const BoostTuple2D &e)
{
std::size_t seed = 0;
boost::hash_combine(seed, e.tuple.get<0>());
boost::hash_combine(seed, e.tuple.get<1>());
return seed;
}

Если у вас возникли проблемы с размещением их в собственном исходном файле, но при оставлении объявления в hedaer, возможно, возникла проблема с пространством имен, в которое вы их помещаете. Мне нужна эта версия кода, чтобы помочь.

Как примечание, кортежи уже должны иметь operator== определяется, так что вы можете использовать это вместо сравнения элемента по элементу самостоятельно (по умолчанию это уже делается).

1

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector