C++11 添加了许多新的类模板,允许静态测试类型特征,即在编译时检测问题。我正在为一个类编写一个测试,我需要确保给定的方法是公开的。
“动态”解决方案是创建一个对象并调用该方法,如果它不起作用,编译器会抱怨。但是可能会发生不同类型的错误,这会使生成的错误消息更加混乱。如果可能,最好使用静态断言测试方法访问级别。
有可能还是我真的必须为此创建一个对象?
(另外,如果我需要该方法是私有/受保护的,我该怎么办)
C++11 添加了许多新的类模板,允许静态测试类型特征,即在编译时检测问题。我正在为一个类编写一个测试,我需要确保给定的方法是公开的。
“动态”解决方案是创建一个对象并调用该方法,如果它不起作用,编译器会抱怨。但是可能会发生不同类型的错误,这会使生成的错误消息更加混乱。如果可能,最好使用静态断言测试方法访问级别。
有可能还是我真的必须为此创建一个对象?
(另外,如果我需要该方法是私有/受保护的,我该怎么办)
这为我编译:
#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, "");
}
据我所知,以下是符合标准的:
#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";
}
另一方面,编译器对这种语言怪癖的支持很差。
Clang 3.2编译并工作。 gcc 4.7.2无法构建。 英特尔 13.0.1编译但返回错误值(在每种情况下都为真!)