3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

メンバ変数が構造体の何番目のメンバかをメンバ変数ポインタから推測(出来たら)する

Last updated at Posted at 2018-05-01

やりたいこと

get_index(&Point::y);  // 1
get_index(&Point::z);  // 2

こういう感じに「メンバ変数ポインタ→それが何番目の構造体の要素か」をしりたい

実装方法

構造化束縛で取り出した変数の参照のポインタと変数ポインタを比較していくことで取得することができる

実装例

get_index.hpp
#include <cassert>

template<class T,class R>
std::size_t get_index3(R T::*p){
    T t;
    auto &[e0,e1,e2] = t;
    int idx=0;
    for(auto tp:{&e0,&e1,&e2}){
        if(tp == &(t.*p))
            return idx;
        idx+=1;
    }
    return 42;
}
main.cpp
struct Point{
    int x;
    int y;
    int z;
};
int main()
{
    std::size_t x = get_index3(&Point::x);
    std::size_t y = get_index3(&Point::y);
    std::size_t z = get_index3(&Point::z);
    assert(x==0);
    assert(y==1);
    assert(z==2);
}

やったー

コンパイル時

型の時間の話

コンパイル時に処理する場合、上の実装だと
任意の構造体のコンストラクタ呼び出しは定数式ではない可能性が高いため T t の部分が問題になる
そのため、コンストラクタの呼び出しは実行時までしないことにする

コンストラクタの呼び出しをしないと変数の値は未定義になるのでダメそうだが、変数のアドレスには影響を及ぼさないため定数式にすることができる1

実装例

get_index.hpp
#include <iostream>

template<class T>
class Class{
    static inline T t{};
public:
    template<auto p>
    static constexpr std::size_t get(){
        auto &[e0,e1,e2] = t;
        int idx=0;
        for(auto tp:{&e0,&e1,&e2}){
            if(tp == &(t.*p))
                return idx;
            idx+=1;
        }
        return 42;
    }
};

main.cpp
struct S{
    std::string x;
    std::string y;
    std::string z;
};

int main()
{
    constexpr auto x = Class<S>::get<&S::x>();
    constexpr auto y = Class<S>::get<&S::y>();
    constexpr auto z = Class<S>::get<&S::z>();
    static_assert(x==0);
    static_assert(y==1);
    static_assert(z==2);
}

gcc 7.3 : https://wandbox.org/permlink/pJTCcz9mDKesTDdJ
clang 6.0: https://wandbox.org/permlink/CSF5ZK8uvZ28AAQu


  1. たぶん。未調査 

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?