C++ 11增加了許多新的類模板,它們允許靜態地測試類型特徵,即在編譯時檢測問題。我正在爲一門課寫作測試,我需要確保給定的方法是公開的。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