2013-08-27 2 views
1

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

В классе я использую boost :: unordered_map для хранения оценок функций, чтобы я не вызывал ненужную функцию. Во время интерполяции я уточняю сетку так, чтобы она достаточно ее описывала (исходя из ее кривизны). Я локально подразделяю меш, так что, если мои исходные точки были в x = 0, .5, 1, следующий набор может быть x = 0, .25, .5, 1, где мне нужно было бы только оценить на x = 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; 
} 

В моем заголовке У меня есть структура и ЬурейеЕ:

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

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

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

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++ newbee, так что надеюсь, что-то простое, что я не получаю. Благодаря!

ответ

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==, поэтому вы можете использовать это вместо сравнения элемента по элементу самостоятельно (по умолчанию уже это делает).

+0

Благодарим вас, что на самом деле происходит компиляция и работа (встроенный). Я не думаю, что вокруг встроенного? – ccook

+0

@ccook: вы помещаете объявления в заголовок, а затем определяете их исходный файл. Вы сказали в своем посте, что у вас возникла проблема, что он не работает, когда вы его пробовали, но это должно быть возможно. –