C ++ 11 есть ли способ проверить уровень доступа метода статически?

В C ++ 11 добавлено множество новых шаблонов классов, которые позволяют статически тестировать свойства типов, то есть обнаруживать проблемы во время компиляции. Я пишу тест для класса, и мне нужно убедиться, что данный метод общедоступен.

«Динамическое» решение состоит в том, чтобы создать объект и вызвать метод, тогда компилятор будет жаловаться, если он не работает. Но возможно, что возникнет ошибка другого типа, и полученное сообщение об ошибке будет более запутанным. Если возможно, лучше всего проверить уровень доступа к методу, используя статическое утверждение.

Это возможно, или я действительно должен создать объект для этого?

(также, что мне делать, если мне нужно, чтобы метод был закрытым / защищенным)

0

Решение

Это компилирует для меня:

#include <type_traits>

namespace has_foo_imp
{

template <class T>
auto
test(T&& t) -> decltype(t.foo(), std::true_type());

auto
test(...) -> std::false_type;

}  // has_foo_imp

template <class T>
struct has_foo
: public std::integral_constant<bool,
decltype(has_foo_imp::test(std::declval<T>()))::value>
{
};

class A
{
void foo();
public:
};

class B
{
public:
void foo();
};

int
main()
{
static_assert(!has_foo<A>::value, "");
static_assert( has_foo<B>::value, "");
}
2

Другие решения

Насколько я могу сказать, следующее соответствие стандартам:

#include <type_traits>

template<typename T,typename=void>
struct NullaryFooCanBeCalled:std::false_type {};

template<typename T>
struct NullaryFooCanBeCalled<
T,
typename std::enable_if<
std::is_same<
decltype(std::declval<T>().Foo()),
decltype(std::declval<T>().Foo())
>::value >::type
>:
std::true_type {};struct PrivateFoo {private:void Foo() {}};
struct PublicFoo {public:void Foo() {}};
struct ProtectedFoo {protected:void Foo() {}};
struct StrangeFoo {
struct Bar { void operator()() {}; };
Bar Foo;
};

#include <iostream>

int main() {
std::cout << "PrivateFoo:" << NullaryFooCanBeCalled<PrivateFoo>::value << "\n";
std::cout << "PublicFoo:" << NullaryFooCanBeCalled<PublicFoo>::value << "\n";
std::cout << "ProtectedFoo:" << NullaryFooCanBeCalled<ProtectedFoo>::value << "\n";
std::cout << "StrangeFoo:" << NullaryFooCanBeCalled<StrangeFoo>::value << "\n";
}

С другой стороны, поддержка компилятора недостаточна для этой странной особенности.

Лязг 3,2 компилирует и работает. gcc 4.7.2 не в состоянии построить. Intel 13.0.1 компилирует, но возвращает неправильные значения (правда в каждом случае!)

2

По вопросам рекламы [email protected]