Как я могу определить, является ли тип видимой основой другого типа? - PullRequest
13 голосов
/ 27 марта 2012

Если я делаю

struct A{};
struct C:private A{};

typedef char (&yes)[1];
typedef char (&no)[2];

template <typename B, typename D>
struct Host
{
 operator B*() const;
 operator D*();
};

template <typename B, typename D>
struct is_base_of
{
template <typename T> 
static yes check(D*, T);
static no check(B*, int);

static const bool value = sizeof(check(Host<B,D>(), int())) == sizeof(yes);
};

int main(){
 std::cout<<is_base_of<A,C>::value<<std::endl;
}

Я получаю 1. Я хотел бы получить 0, когда C является частным A, и 1, когда C является публичным A.

[код получен из Как работает `is_base_of`? ]

Ответы [ 3 ]

4 голосов
/ 22 мая 2012

У вас есть доступ к компилятору с поддержкой C ++ 11?

Если это так, вы можете объединить использование Чадом static_cast с decltype для создания очень простой реализации черты типа (как показано в в этом вопросе ). Согласно предложению Джонатана Уэйкли, ссылки были заменены указателями, чтобы избежать ложных срабатываний, когда D определяет operator B&().

template<typename> struct AnyReturn { typedef void type; };

template<typename B, typename D, typename Sfinae = void>
struct is_base_of: std::false_type {};

template<typename B, typename D>
struct is_base_of<B, D,
    typename AnyReturn< decltype( static_cast<B*>( std::declval<D*>() ) ) >::type
>: std::true_type {};

При использовании gcc 4.7:

struct Base {};
struct PublicDerived  : public  Base {};
struct PrivateDerived : private Base {};

int main()
{
    std::cout << is_base_of<Base, PublicDerived >::value << std::endl; // prints 1
    std::cout << is_base_of<Base, PrivateDerived>::value << std::endl; // prints 0
    return 0;
}
0 голосов
/ 21 мая 2012

Чтобы применить трюк разрешения перегрузки во время компиляции для обнаружения спецификаторов доступа, вам, по крайней мере, понадобится учитывать спецификаторы доступа во время разрешения перегрузки времени. Это не относится к C ++ 03 , поэтому это невозможно сделать. Я полагаю, что C ++ 11 меняет это, поэтому с некоторыми искусственными преобразованиями и SFINAE вы сможете реализовать это.

Обновление: Я перехожу n3242 Раздел «Разрешение перегрузки», и я не могу найти ничего, что указывало бы на то, что спецификаторы доступа рассматриваются для разрешения перегрузки на C ++ 11.

0 голосов
/ 27 марта 2012

Вам нужно что-то, что можно оценить во время выполнения, или будет достаточно простой ошибки времени компиляции?

struct A {};
struct B : private A {};

int main()
{
   B b;

   // gives error C2243: 'static_cast' : conversion from 'B *' to 'A &' exists, but is inaccessible
   A& a = static_cast<A&>(b);

   return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...