我有一个Lua State类的模板化方法,它测试给定索引处的对象是否属于给定类型:
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”方法的类添加特化:
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似乎并不相信这一点。 / p>
这看起来应该很简单,但我一直在试图实现它。
答案 0 :(得分:1)
将始终使用显式模板参数调用类方法is()
,例如:is<some_type>(value)
。因此,在这种情况下,您可以将其作为static
函数包含在类中,以简化template
特化。
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(...); }
};
<强>专业化强>:
现在我们保留typename = void
以便于SFINAE如下:
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);
它编译&amp;在我的环境中工作,因此,它也适合你!
修改:我发现您在此方法中使用了this
。在这种情况下,您的方法可能如下所示:
template<typename T, typename = void>
struct X { // default
static bool is (Lua* const this_, int idx) { return ...; }
};
// ... other specializations with similar syntax
答案 1 :(得分:1)
您可以在decltype
:
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;
};