2015-09-25 8 views
5

struct Fooがあり、Foointがあるかどうかを調べたいとします。構造体に特定の型のメンバーがあるかどうかを確認

struct Foo { int a; char c; }; 
has_int<Foo>::value; // should be true 

これは、特定の種類のチェック、私が実際にしたいと思うものをの最も基本的な形式である:私は何を私の最後にそれを変換することができ、上記を行う方法を知っていた場合は

has_type<Foo, int>::value; 

目標は次のとおりです。

私が試したもののためとして
has_pointer<Foo>::value; // false 
struct Bar { int a; void *b; }; 
has_pointer<Bar>::value; // true 

、それが始めるのは難しい、私は構造体に含まれる種類のパックを得ることができれば、私は書くことができるということであると考えることができる最高残り:

template <typename... Ts> 
constexpr bool any_is_pointer() noexcept { 
    return (... || std::is_pointer_v<Ts>); 
} 

私が求めていることは、非常にうまくいかない可能性があるようです。私は重複を見つけることができませんでしたが、私はそれがそこにあるかもしれないことができなかったことに驚いた。

+0

これは不可能ですが、C++にはリフレクションがありません。しかし、 'std :: tuple'のようなものは非常に簡単です。 – Barry

+0

基本的に、あなたは反射を望む。 C++はリフレクションを行いません。しかし、私は助けることはできませんが、疑問に思っています:あなたは何とか 'has_int'を実装することができたとします - それをどのように使用する予定ですか?あなたが解決しようとしている本当の問題は何ですか? –

+0

@IgorTandetnik私は、ポインタや参照を含む構造体を微妙に扱う必要がある状況にあります。コンパイル時にどのような操作を許可するかを決めるのがポイントです。私は本当に詳細なレベルで説明することはできません。 –

答えて

1

他の人が言っているように、あなたが望むのは、バニラC++では今のところ不可能です。しかし、あなたが定義で操作する必要があるタイプと一緒に特定のコンパイル時の情報を提供できる場合は、あなたがしようとしていることを行うことができます。

ブースト融合ライブラリのアダプターを使用すると、既存の構造を融合コンテナに変更したり、融合コンテナをモデル化する新しい構造を定義することができます。あなたは、あなたがやりたいコンパイル時のチェックのタイプをしたいと思うどんなboost :: mplアルゴリズムを使用することができます。

#include <boost/fusion/adapted/struct/define_struct.hpp> 
#include <boost/mpl/contains.hpp> 

BOOST_FUSION_DEFINE_STRUCT(
    (your_namespace), foo, 
    (int, a) 
    (char, c)) 

template<typename source_type, typename search_type> 
struct has_type 
{ 
    typedef typename boost::mpl::contains<source_type, search_type>::type value_type; 
    static const bool value = value_type::value; 
}; 

#include <iostream> 

int main() 
{ 
    bool foo_has_int_pointer = has_type<your_namespace::foo, int*>::value; 
    bool foo_has_int = has_type<your_namespace::foo, int>::value; 

    std::cout << "foo_has_int_pointer: " << foo_has_int_pointer << "\n"; 
    std::cout << "foo_has_int: " << foo_has_int << "\n"; 

    your_namespace::foo my_foo; 

    my_foo.a = 10; 
    my_foo.c = 'x'; 

    std::cout << "my_foo: " << my_foo.a << ", " << my_foo.c; 
} 

ビューここでは例の出力や混乱:あなたが見ることができるようにhttp://ideone.com/f0Zc2M

は、あなたが使用

はあなたの struct foo、およびご希望の has_typeコンパイル時のアルゴリズムを使用して、この例を考えてみましょうコンパイル時にメンバーを操作したい structを定義するBOOST_FUSION_DEFINE_STRUCTマクロ。融合は、このような構造を定義するためのいくつかの他のマクロと、すでに定義された構造を適合させるためのマクロを提供します。それらをチェックしてください here

もちろん、あなたはおそらく既にここでダウンサイドを伝えることができます。 has_typeは、source_typeがboost :: mpl/boost :: fusionシーケンスである場合にのみ機能します。これは、このようにしてコンパイル時に推論したいタイプであれば、マクロを使用して定義または適応する必要があることを意味します。これは、任意のライブラリユーザー定義型で動作するように意図されたライブラリを作成している場合には、受け入れられない場合があります。