【问题标题】:Trouble with boost::tuple in boost::unordered_map within a templated class模板类中 boost::unordered_map 中 boost::tuple 的问题
【发布时间】:2013-08-27 14:47:11
【问题描述】:

我编写了一个方法,可以在 C++ 中自动插入一个昂贵的 2D 函数。我现在试图让类接受一个函数指针,以便可以插入任何函数。为此,我似乎需要一个模板类,以便我可以为每个需要评估函数指针的对象模板化它。在我意识到我需要在头文件中完全定义类之后,这部分并不是那么糟糕,以便链接器可以为所需的每个对象模板化类。现在麻烦了。

在类中,我使用 boost::unordered_map 来存储函数评估,这样我就不会不必要地调用函数。在插值过程中,我细化了一个网格,以便它充分描述它(基于它的曲率)。我在局部细分网格,所以如果我的原始点位于 x=0, .5, 1,下一组可能是 x=0, .25, .5, 1,我只需要在x = .25 第二次通过。它使用硬编码函数自行工作,代替动态函数指针。

我遇到的麻烦是为 boost::tuple 定义必要的运算符和 hash_value 函数。如果我把它放在标题中,它们会被定义多次(对于标题的每个包含)。如果我尝试将其编译为对象并将其链接到其中,则链接器无法找到定义。我需要在课堂上引用的两个定义:

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++ 新手,所以希望它是我没有得到的简单的东西。谢谢!

【问题讨论】:

    标签: c++ boost function-pointers unordered-map class-template


    【解决方案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==,因此您可以使用它而不是自己逐个元素进行比较(默认已经这样做了)。

    【讨论】:

    • 谢谢,这实际上可以编译和工作(内联)。我不认为内联周围有距离?
    • @ccook:您可以将声明放在标题中,然后在源文件中定义它们。你在你的帖子中说你有一个问题,当你尝试它时它不起作用,但它应该是可以的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-09
    • 2011-05-16
    • 2011-06-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多