2

以下のコードはこちら: https://ideone.com/XnxAyw

私が得るコンパイルエラーは次のとおりです。

prog.cpp: In member function ‘size_t list_base<T, NODE, true>::offset()’:
prog.cpp:26:22: error: expected unqualified-id before ‘*’ token
return offsetof(T, *NODE);
                   ^
prog.cpp:26:22: error: expected ‘)’ before ‘*’ token

Visual Studio はoffsetof(type, 'pointer to member')を使用しても問題ありませんが、それは緩いからですか? もしそうなら、メンバテンプレート引数へのポインタで offsetof() を使用する標準に準拠した方法を知っている人はいますか?

#include <stdio.h>
#include <stddef.h>

template <typename T>
struct list_node_base
{
    T *next;
    T *prev;
};

template <typename T>
struct linked_list_node
{
    list_node_base<T> list_node;
};

template <typename T, linked_list_node<T> T::*NODE, bool is_member>
struct list_base
{
};

template <typename T, linked_list_node<T> T::*NODE>
struct list_base<T, NODE, true> : linked_list_node<T>
{
    size_t offset()
    {
        return offsetof(T, *NODE);
    }
};

template <typename T, linked_list_node<T> T::*NODE>
struct list_base<T, NODE, false> : linked_list_node<T>
{
    size_t offset()
    {
        return offsetof(T, decltype(*this)::list_node);
    }
};

template <typename T, linked_list_node<T> T::*NODE = nullptr>
struct linked_list : list_base<T, NODE, (linked_list_node<T> T::*)nullptr != NODE>
{
};

struct foo : linked_list_node<foo>
{
};

struct bar
{
    linked_list_node<bar> node;
};

linked_list<foo> foo_list;
linked_list<bar, &bar::node> bar_list;

int main(int, char **)
{
    return 0;
}

ここでの別の試み: https://ideone.com/HD8PI0

この時点で完全に困惑しました。2 回目の試みは次のとおりです。

#include <stdio.h>
#include <stddef.h>

template <typename T> struct list_node_base
{
    T *next;
    T *prev;
};

template <typename T>
struct linked_list_node
{
    list_node_base<T> list_node;
};

template <typename T, linked_list_node<T> T::*NODE, bool is_member>
struct list_base
{

};

template <typename T, typename R, R T::*M>
size_t offset_of()
{
    return reinterpret_cast<size_t>(&(((T*)0)->*M));
}

template <typename T, typename M> M get_member_type(M T::*);
template <typename T, typename M> T get_class_type(M T::*);

#define OFFSET_OF(m) offset_of<decltype(get_class_type(m)), decltype(get_member_type(m)), m>()

template <typename T, linked_list_node<T> T::*NODE>
struct list_base<T, NODE, true> : linked_list_node<T>
{
    size_t offset()
    {
        return OFFSET_OF(&T::*NODE);
    }
};

template <typename T, linked_list_node<T> T::*NODE>
struct list_base<T, NODE, false> : linked_list_node<T>
{
    size_t offset()
    {
        return OFFSET_OF(&T::list_node);
    }
};

template <typename T, linked_list_node<T> T::*NODE = nullptr>
struct linked_list : list_base<T, NODE, (linked_list_node<T> T::*)nullptr != NODE>
//struct linked_list : list_base<T, NODE, NODE>
{
};

struct foo : linked_list_node<foo>
{
};

struct bar
{
    linked_list_node<bar> node;
};

linked_list<foo> foo_list;
linked_list<bar, &bar::node> bar_list;

int main(int, char **)
{
    return 0;
}
4

1 に答える 1