2013-02-18 108 views
0

C++ 11增加了许多新的类模板,它们允许静态地测试类型特征,即在编译时检测问题。我正在为一门课写作测试,我需要确保给定的方法是公开的。C++ 11有没有一种方法来静态测试方法访问级别?

“动态”解决方案是创建一个对象,并调用该方法,那么如果它不工作,编译器会抱怨。但可能会发生不同类型的错误,并且会导致产生的错误消息更加混乱。如果可能的话,最好使用静态断言来测试方法访问级别。

是否有可能还是我真的要创建一个对象?

(也,我该怎么办,如果我需要的方法是私有/保护)

+0

如果编译器抱怨,它不是一个“动态”解决方案... – 2013-02-18 14:16:41

+1

呃,调用方法? – Collin 2013-02-18 14:28:05

+0

@KerrekSB对不起,我的错误。 – cfa45ca55111016ee9269f0a52e771 2013-02-18 15:12:51

回答

2

这编译对我来说:

#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, ""); 
} 
+0

为什么不直接继承'公共decltype(has_foo_imp ::测试(...))'的解决方案? – Xeo 2013-02-18 15:46:53

+0

这实际上在Clang 3.2上编译,但不在GCC 4.7.2上编译。我不知道谁是对的,为什么? – 2013-02-18 15:53:54

+0

@AndyProwl [锵(http://stackoverflow.com/questions/8984013/can-sfinae-detect-private-access-violations)我想。 – Yakk 2013-02-18 15:58:14

2

至于我可以告诉大家,以下是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)

+0

这看起来很复杂,我不明白它是如何工作的。如果编译器支持很差(我使用GCC),我可能不应该使用它,但无论如何 - 你能否用文字解释它是如何工作的?我的意思是,它依赖的语言原则是什么? – cfa45ca55111016ee9269f0a52e771 2013-02-18 18:39:28

+0

SFINAE - 基本上,我测试't.Foo()'是否格式良好,如果是,模板特化与':: value = true'成立,否则':: value = false'成立。问题在于,这种不是错误的特定替换失败在某些编译器中被视为错误。另一方面,标准足够复杂,我可能是错的,也许它应该是一个错误! – Yakk 2013-02-18 18:44:21

+0

然后我想这不是一个简单的方法......如果有些编译器支持它而其他编译器不支持,最好等到它支持得更好(或者C++可以更好地检查访问级别,例如新的类模板,它允许直接检查方法访问级别,如std :: is_constructible) – cfa45ca55111016ee9269f0a52e771 2013-02-18 18:51:28

相关问题