C++ 11有没有一种方法来静态测试方法访问级别?
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, "");
}
至于我可以告诉大家,以下是standards compliant:
#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无法建立。 Intel 13.0.1编译但返回错误的值(在任何情况下均为true)
这看起来很复杂,我不明白它是如何工作的。如果编译器支持很差(我使用GCC),我可能不应该使用它,但无论如何 - 你能否用文字解释它是如何工作的?我的意思是,它依赖的语言原则是什么? – cfa45ca55111016ee9269f0a52e771 2013-02-18 18:39:28
SFINAE - 基本上,我测试't.Foo()'是否格式良好,如果是,模板特化与':: value = true'成立,否则':: value = false'成立。问题在于,这种不是错误的特定替换失败在某些编译器中被视为错误。另一方面,标准足够复杂,我可能是错的,也许它应该是一个错误! – Yakk 2013-02-18 18:44:21
然后我想这不是一个简单的方法......如果有些编译器支持它而其他编译器不支持,最好等到它支持得更好(或者C++可以更好地检查访问级别,例如新的类模板,它允许直接检查方法访问级别,如std :: is_constructible) – cfa45ca55111016ee9269f0a52e771 2013-02-18 18:51:28
如果编译器抱怨,它不是一个“动态”解决方案... – 2013-02-18 14:16:41
呃,调用方法? – Collin 2013-02-18 14:28:05
@KerrekSB对不起,我的错误。 – cfa45ca55111016ee9269f0a52e771 2013-02-18 15:12:51