具有特定方法的 类 的模板专业化
Template specialization for classes which have a certain method
我有一个 Lua 状态 class 的模板化方法,它测试给定索引处的对象是否属于给定类型:
template<typename T> bool is(int idx) {
return luaL_testudata(L, idx, std::remove_pointer<T>::type::name) != NULL;
};
和一些专业:
template<> inline bool State::is<bool>(int i){ return lua_isboolean(this->L, i); }
template<> inline bool State::is<int>(int i){ return lua_isinteger(this->L, i); }
//etc...
现在我想为任何具有静态 "lua_test" 方法的 class 添加特化:
template<> inline bool State::is<T>(int i){ return T::lua_test(this->L, i); }
但我不知道正确的语法。我最接近的是:
template <class T>
inline auto State::is(int idx) ->
decltype(std::declval<T>.lua_test(this, idx), true)
{
return T::lua_test(this, idx);
}
编译失败,因为显然类型不匹配:
templates.hpp:87:13: error: prototype for ‘decltype ((declval<T>.lua_test(((Lua::State*)this), idx), true)) Lua::State::is(int)’ does not match any in class ‘Lua::State’
inline auto State::is(int idx) ->
^~~~~
In file included from [...],
from debug.cpp:1:
get.hpp:6:27: error: candidate is: template<class T> bool Lua::State::is(int)
template<typename T> bool is(int idx) {
这个想法应该是 decltype
语句的计算结果为 decltype(true)
(由于逗号运算符),即 bool
,但 gcc 似乎并不相信这一点.
这看起来应该很简单,但我一直没有尝试实现它。
class 方法 is()
将始终使用显式模板参数调用,例如:is<some_type>(value)
。因此,在这种情况下,为了简化 template
专业化,您可以将其作为 static
函数包含在 class 中。
template<typename T, typename = void>
struct X { // default
static bool is (int idx) { return ...; }
};
template<>
struct X<int, void> { // `int` specialization
static bool is (int idx) { return lua_isinteger(...); }
};
template<>
struct X<bool, void> { // `bool` specialization
bool is (int idx) { return lua_isboolean(...); }
};
专业:
现为SFINAE预留typename = void
如下:
template<typename T> struct void_ { using type = void; };
template<typename T> // specialization for those, who contain `lua_test`
struct X<T, typename void_<decltype(&T::lua_test)>::type> {
static bool is (int idx) { return T::lua_test(...); }
};
用法:
X<some_class>::is(0);
X<int>::is(1);
X<bool>::is(2);
X<some_class_with_lua_test_function>::is(3);
它在我的环境中编译和工作,因此,它也应该适合你!
编辑:我看到你在这个方法中使用了this
。在这种情况下,您的方法可能如下所示:
template<typename T, typename = void>
struct X { // default
static bool is (Lua* const this_, int idx) { return ...; }
};
// ... other specializations with similar syntax
您可以简单地重复 decltype
中的 return:
struct State
{
// ....
template <class T>
auto is(int idx) -> decltype(T::lua_test(this, idx))
{
return T::lua_test(this, idx);
}
};
对于您的情况,您必须做一些工作才能避免两种方法之间的调用不明确。
struct low_priority {};
struct high_priority : low_priority {};
struct State
{
public:
template<typename T>
bool is(int idx) {
return is_impl<T>(idx, high_priority{});
}
private:
template<typename T>
bool is_impl(int idx, low_priority) {
std::cout << "generic\n";
return luaL_testudata(L, idx, std::remove_pointer<T>::type::name) != NULL;
}
template <class T>
auto is_impl(int idx, high_priority) -> decltype(T::lua_test(this, idx))
{
std::cout << "LuaTest\n";
return T::lua_test(this, idx);
}
LuaState L;
};
我有一个 Lua 状态 class 的模板化方法,它测试给定索引处的对象是否属于给定类型:
template<typename T> bool is(int idx) {
return luaL_testudata(L, idx, std::remove_pointer<T>::type::name) != NULL;
};
和一些专业:
template<> inline bool State::is<bool>(int i){ return lua_isboolean(this->L, i); }
template<> inline bool State::is<int>(int i){ return lua_isinteger(this->L, i); }
//etc...
现在我想为任何具有静态 "lua_test" 方法的 class 添加特化:
template<> inline bool State::is<T>(int i){ return T::lua_test(this->L, i); }
但我不知道正确的语法。我最接近的是:
template <class T>
inline auto State::is(int idx) ->
decltype(std::declval<T>.lua_test(this, idx), true)
{
return T::lua_test(this, idx);
}
编译失败,因为显然类型不匹配:
templates.hpp:87:13: error: prototype for ‘decltype ((declval<T>.lua_test(((Lua::State*)this), idx), true)) Lua::State::is(int)’ does not match any in class ‘Lua::State’
inline auto State::is(int idx) ->
^~~~~
In file included from [...],
from debug.cpp:1:
get.hpp:6:27: error: candidate is: template<class T> bool Lua::State::is(int)
template<typename T> bool is(int idx) {
这个想法应该是 decltype
语句的计算结果为 decltype(true)
(由于逗号运算符),即 bool
,但 gcc 似乎并不相信这一点.
这看起来应该很简单,但我一直没有尝试实现它。
class 方法 is()
将始终使用显式模板参数调用,例如:is<some_type>(value)
。因此,在这种情况下,为了简化 template
专业化,您可以将其作为 static
函数包含在 class 中。
template<typename T, typename = void>
struct X { // default
static bool is (int idx) { return ...; }
};
template<>
struct X<int, void> { // `int` specialization
static bool is (int idx) { return lua_isinteger(...); }
};
template<>
struct X<bool, void> { // `bool` specialization
bool is (int idx) { return lua_isboolean(...); }
};
专业:
现为SFINAE预留typename = void
如下:
template<typename T> struct void_ { using type = void; };
template<typename T> // specialization for those, who contain `lua_test`
struct X<T, typename void_<decltype(&T::lua_test)>::type> {
static bool is (int idx) { return T::lua_test(...); }
};
用法:
X<some_class>::is(0);
X<int>::is(1);
X<bool>::is(2);
X<some_class_with_lua_test_function>::is(3);
它在我的环境中编译和工作,因此,它也应该适合你!
编辑:我看到你在这个方法中使用了this
。在这种情况下,您的方法可能如下所示:
template<typename T, typename = void>
struct X { // default
static bool is (Lua* const this_, int idx) { return ...; }
};
// ... other specializations with similar syntax
您可以简单地重复 decltype
中的 return:
struct State
{
// ....
template <class T>
auto is(int idx) -> decltype(T::lua_test(this, idx))
{
return T::lua_test(this, idx);
}
};
对于您的情况,您必须做一些工作才能避免两种方法之间的调用不明确。
struct low_priority {};
struct high_priority : low_priority {};
struct State
{
public:
template<typename T>
bool is(int idx) {
return is_impl<T>(idx, high_priority{});
}
private:
template<typename T>
bool is_impl(int idx, low_priority) {
std::cout << "generic\n";
return luaL_testudata(L, idx, std::remove_pointer<T>::type::name) != NULL;
}
template <class T>
auto is_impl(int idx, high_priority) -> decltype(T::lua_test(this, idx))
{
std::cout << "LuaTest\n";
return T::lua_test(this, idx);
}
LuaState L;
};