2013-02-18 124 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

相關問題