11

運が悪かったのでググってみたので、ここでやってみます。

いくつかのクラスがあり、それぞれがメンバーを定義していますstruct foo。このメンバータイプ自体は、以前のクラスの1つから継承できるため、メンバータイプ自体fooを取得できます。foo

fooテンプレートメタプログラミング(以下を参照)を使用してネストされた型にアクセスしたいのですが、c ++名の挿入では問題が発生します。これは、上部のfoo型の名前が下部の型に挿入され、下部のfoo型にアクセスするときに上部の名前が解決されるためです。A::foo::foo

次に例を示します。

#include <type_traits>

struct A;
struct B;

struct A {
    struct foo;
};

struct B {
    struct foo;
};

struct A::foo : B { };
struct B::foo : A { };

// handy c++11 shorthand
template<class T>
using foo = typename T::foo;

static_assert( std::is_same< foo< foo< A > >, foo< B > >::value, 
               "this should not fail (but it does)" );

static_assert( std::is_same< foo< foo< A > >, foo< A > >::value, 
               "this should fail (but it does not)" );

参考までに、私は関数導関数を実装していますfooが、導関数タイプです。上記の状況は、たとえばsin/cosで発生します。

TLDR:どうすれfoo<foo<A>>foo<B>、ではなく、どうすればいいfoo<A>ですか?

ありがとう !

4

1 に答える 1

1

これは実際には自動ソリューションではありませんが、問題を解決します。タイプは基本クラスにtypedefを提供し、このtypedefの不在/存在はSFINAEを介して検出され、ネストされたfooは基本または通常のルックアップのいずれかを介して検出されます。

さらに自動化が必要な場合は、を自動化しhas_baseて既知の塩基のリストを確認できます。is_base_of

#include <type_traits>
template <typename T>
struct has_base
{
    typedef char yes[1];
    typedef char no[2];

    template <typename C>
    static yes& test(typename C::base*);

    template <typename>
    static no& test(...);

    static const bool value = sizeof(test<T>(0)) == sizeof(yes);
};

struct A {
    struct foo;
};

struct B {
    struct foo;
};

struct A::foo : B { typedef B base; };
struct B::foo : A { typedef A base; };

template<typename T, bool from_base = has_base<T>::value >
struct foo_impl {
  typedef typename T::base::foo type;
};

template<typename T> 
struct foo_impl<T, false> {
  typedef typename T::foo type;
};

template<typename T>
using foo = typename foo_impl<T>::type;

static_assert( std::is_same< foo< foo<A> >::, foo< B > >::value, 
               "this should not fail (but it does)" );

static_assert( std::is_same< foo< foo< A > >, foo< A > >::value, 
               "this should fail (but it does not)" );
int main()
{

  return 0;
}
于 2012-10-17T16:12:04.077 に答える