有一個(編譯器特定的)的方式來測試一個類型是否是在一定的命名空間,但是我會讓你決定是否比你還是不是更好:
#include <utility>
#include <type_traits>
namespace helper
{
class ctstring
{
public:
constexpr ctstring(const char* string) : _string(string)
{
}
constexpr const char* c_str() const
{
return _string;
}
constexpr bool begins_with(const ctstring other) const
{
return !*other.c_str() ||
(*_string && *_string == *other.c_str() &&
ctstring(_string + 1).begins_with(other.c_str() + 1));
}
private:
const char* _string;
};
template <typename T>
constexpr bool is_type_in_namespace(const ctstring name)
{
#if defined(_MSC_VER)
#define PRETTY_FUNCTION_OFFSET_1 \
(sizeof("void __cdecl helper::is_type_in_namespace<struct ") - 1)
#define PRETTY_FUNCTION_OFFSET_2 \
(sizeof("void __cdecl helper::is_type_in_namespace<class ") - 1)
return ctstring(__FUNCSIG__ + PRETTY_FUNCTION_OFFSET_1).begins_with(name) ||
ctstring(__FUNCSIG__ + PRETTY_FUNCTION_OFFSET_2).begins_with(name);
#undef PRETTY_FUNCTION_OFFSET_1
#undef PRETTY_FUNCTION_OFFSET_2
#elif defined(__clang__)
return ctstring(__PRETTY_FUNCTION__ +
(sizeof("bool helper::is_type_in_namespace(const "
"helper::ctstring) [T = ") -
1))
.begins_with(name);
#elif defined(__GNUC__)
return ctstring(__PRETTY_FUNCTION__ +
(sizeof("constexpr bool "
"helper::is_type_in_namespace(helper::ctstring) "
"[with T = ") -
1))
.begins_with(name);
#else
#error "Your compiler is not supported, yet."
#endif
}
}
// -- Test it
namespace sample
{
struct True_X;
class True_Y;
template <typename>
class True_T;
template <typename A>
using True_U = True_T<A>;
}
struct False_X;
class False_Y;
template <typename>
class False_T;
template <typename A>
using False_U = False_T<A>;
void test1()
{
static_assert(helper::is_type_in_namespace<sample::True_X>("sample::"), "1");
static_assert(helper::is_type_in_namespace<sample::True_Y>("sample::"), "2");
static_assert(helper::is_type_in_namespace<sample::True_T<int>>("sample::"), "3");
static_assert(helper::is_type_in_namespace<sample::True_U<int>>("sample::"), "4");
static_assert(!helper::is_type_in_namespace<False_X>("sample::"), "5");
static_assert(!helper::is_type_in_namespace<False_Y>("sample::"), "6");
static_assert(!helper::is_type_in_namespace<False_T<int>>("sample::"), "7");
static_assert(!helper::is_type_in_namespace<False_U<int>>("sample::"), "8");
}
namespace sample
{
void test2()
{
static_assert(helper::is_type_in_namespace<True_X>("sample::"), "1");
static_assert(helper::is_type_in_namespace<True_Y>("sample::"), "2");
static_assert(helper::is_type_in_namespace<True_T<int>>("sample::"), "3");
static_assert(helper::is_type_in_namespace<True_U<int>>("sample::"), "4");
static_assert(!helper::is_type_in_namespace<::False_X>("sample::"), "5");
static_assert(!helper::is_type_in_namespace<::False_Y>("sample::"), "6");
static_assert(!helper::is_type_in_namespace<::False_T<int>>("sample::"), "7");
static_assert(!helper::is_type_in_namespace<::False_U<int>>("sample::"), "8");
}
namespace inner
{
void test3()
{
static_assert(helper::is_type_in_namespace<::sample::True_X>("sample::"), "1");
static_assert(helper::is_type_in_namespace<::sample::True_Y>("sample::"), "2");
static_assert(helper::is_type_in_namespace<::sample::True_T<int>>("sample::"), "3");
static_assert(helper::is_type_in_namespace<::sample::True_U<int>>("sample::"), "4");
static_assert(!helper::is_type_in_namespace<::False_X>("sample::"), "5");
static_assert(!helper::is_type_in_namespace<::False_Y>("sample::"), "6");
static_assert(!helper::is_type_in_namespace<::False_T<int>>("sample::"), "7");
static_assert(!helper::is_type_in_namespace<::False_U<int>>("sample::"), "8");
}
}
}
void test4()
{
using namespace sample;
static_assert(helper::is_type_in_namespace<True_X>("sample::"), "1");
static_assert(helper::is_type_in_namespace<True_Y>("sample::"), "2");
static_assert(helper::is_type_in_namespace<True_T<int>>("sample::"), "3");
static_assert(helper::is_type_in_namespace<True_U<int>>("sample::"), "4");
}
int main(int argc, char* argv[])
{
test1();
sample::test2();
sample::inner::test3();
test4();
return 0;
}
我測試了這個MSVC2015和一些隨機的在線Clang編譯器和GCC 6.1.0。
思想:
- 測試接受來自命名空間樣品和任何子名字空間類和結構。
- 它不會遭受您的解決方案的缺點
- 您可能想要構建std :: decay_t以刪除CV限定符。
- 顯然代碼需要> = C++ 14 編輯:沒有任何更多,C++ 11是足夠
- 沒有人喜歡宏編輯:除去了大部分的宏
- 的代碼不是非常便攜並且很可能需要某些編譯器和編譯器版本的附加分支。它是由你的要求,如果該解決方案是可以接受的
編輯:重構代碼,使其更清晰,並添加GCC支持。此外,要測試的名稱空間現在可以作爲參數傳遞
此解決方案頗具侵擾性。爲了把它放到一個庫中,我想我將創建一個定義名稱空間的宏,它在'namespace xxx {'後面設置'adl_is_member_of_sample()'。 – Lingxi
順便說一句,有沒有一個名稱爲''is_member_of_sample'模板使用的技術? – Lingxi
@靈溪SFINAE。 –