C++:使用Boost MultiIndex确定指针类型的类

标签 c++ boost types boost-multi-index

这个问题的答案具有普遍适用性,但我将通过以下示例来激发它:

我有以下模板类:

template <typename V>
class Collection
{
public:
    struct id{};
    struct name{};
    // A collection parameterized by type V that is indexed by a string 'name'
    // and a integer 'id'
    // The type V must implement 'get_id()' and a 'get_name()' functions
    typedef multi_index_container <
        V,
        indexed_by<
            ordered_unique<
                tag<id>, const_mem_fun<V, unsigned int, &V::get_id> >,
            ordered_unique<
                tag<name>, const_mem_fun<V, std::string, &V::get_name> >
        >
    > ni_collection;
>

我想修改此模板,以便可以创建包含对象、其指针或引用的集合:Collection<Obj> , Collection<std::unique_ptr<Obj>>Collection<Obj *>

如何修改我的模板来实现此目的?

--- 更新 --- 我在这里发布了一个相关问题: Computing The Type Of A Function Pointer

综合两地的优秀答案,终于达到了我最初的目的。以下是我当前实现的详细信息:

template <typename V>
class Collection
{
private:
// A type-level function that returns the undecorated type of the object
// So unrwap_object_type<Widget *> = Widget
//    unwrap_object_type<std::unique_ptr<Widget>> = Widget
//    unwrap_object_type<Widget> = Widget
template<typename T, typename = void>
struct unwrap_object_type { typedef T type; };

template <typename T>
struct unwrap_object_type<T *, void> { typedef T type; };

template<typename T>
struct unwrap_object_type<T,
    typename std::conditional<false,
        typename T::element_type, void>::type>
{
  typedef typename T::element_type type;
};
////

// So that QHNETO_COLLECTION<Widget>, QHNETO_COLLECTION<Widet *>,
// and QHNETO_COLLECTION<std::unique_ptr<Widget>> are valid
typedef typename unwrap_object_type<V>::type W;

// Tags for the two indices (id and name) of the collection
struct id;
struct name;

// A collection parameterized by type V that is indexed by a string 'name'
// and a integer 'id'
// The type V must implement 'get_id()' and a 'get_name()' functions
typedef multi_index_container <
    V,
    indexed_by<
        ordered_unique<
            tag<id>,
            const_mem_fun<W, unsigned int, &W::get_id> >,
        ordered_unique<
            tag<name>,
            const_mem_fun<W, std::string, &W::get_name> >
    >
> ni_collection;

ni_collection m_collection;
};

最佳答案

详细阐述@sehe的答案:Boost.MultiIndex预定义的键提取器自动处理解除引用(例如,const_mem_fun<foo,bar,&foo::bar>可以按原样与multi_index_containerfoo*一起使用)。您可以利用此功能并编写以下内容(无需任何用户提供的 key 提取器):

Live On Coliru

#include <boost/multi_index_container.hpp>
#include <boost/multi_index/mem_fun.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <memory>

namespace bmi = boost::multi_index;

template<typename T>
struct remove_pointer{using type=T;};

template<typename T>
struct remove_pointer<T*>{using type=T;};

template<typename T>
struct remove_pointer<std::shared_ptr<T>>{using type=T;};

template <typename V> class Collection {
  public:
    struct id;
    struct name;

    using W=typename remove_pointer<V>::type;

    typedef boost::multi_index_container<
        V,
        bmi::indexed_by<
            bmi::ordered_unique<
                bmi::tag<id>,
                bmi::const_mem_fun<W, unsigned int, &W::get_id>
            >,
            bmi::ordered_unique<
                bmi::tag<name>,
                bmi::const_mem_fun<W,const std::string&, &W::get_name> 
            > 
        >
    > ni_collection;
};

struct Demo {
    unsigned _id;
    std::string _name;

    Demo(unsigned _id,const std::string& _name):_id(_id),_name(_name){}

    unsigned           get_id() const { return _id; }
    std::string const& get_name() const { return _name; }
};

int main() {
    Collection<Demo>::ni_collection works{ { 42, "LTUAE" }, { 4, "PI" } };
    Collection<Demo *>::ni_collection also_works{ new Demo{ 42, "LTUAE" }, new Demo{ 4, "PI" } };
    Collection<std::shared_ptr<Demo>>::ni_collection this_too{ std::make_shared<Demo>( 42, "LTUAE" ), std::make_shared<Demo>( 4, "PI" ) };
}

唯一棘手的部分是const_mem_fun使用W =std::remove_pointer<V>::type (即 V 如果 V 是普通类型或它指向的类型(如果它是指针)。

编辑:而不是std::remove_pointer<V> ,更新后的代码使用了手工制作的remove_pointer模板类部分专门化理解T*std::shared_ptr<T> ;您可以将其扩展到涵盖,例如 std::unique_ptr<T>或您需要满足的任何其他智能指针类。

关于C++:使用Boost MultiIndex确定指针类型的类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34688926/

相关文章:

c++ - 如何查看 boost set<cpp_int> 中的下一个和上一个元素

c++ - Qt Ui 命名空间

java - 有没有等同于 Boost::Python for Java 的东西?

c++ - boost::hash<double> 在 RHEL 5.4 64 位上的奇怪行为

c# - 泛型方法的可为空参数类型 <T>?

haskell - 在 Haskell 中对结构相似类型内的值进行操作

c++ - PostgreSQL 将数组或记录作为行返回

c++ - 同一容器中的 IOCP 多个套接字完成端口

c++ - 如何将 graphviz 与 VIsual C++ 链接

matlab - 类型不完整的 Matlab 等式支持