"Could not deduce template argument" 指定模板参数时
"Could not deduce template argument" when template argument is specified
我正在尝试用 C++ 编写我自己的简单反射系统。我有以下测试代码:
#include <cstdio>
#include <xtr1common>
// common base class
struct TypeDescriptor { };
// specialization for primitive types
template<class T>
struct Primitive : public TypeDescriptor
{
static Primitive<T> Instance;
};
Primitive<int> Primitive<int>::Instance;
struct ReflectedType
{
static TypeDescriptor Reflection;
};
// gets an appropriate TypeDescriptor for a type based on whether it has a Reflection member or not.
// if not, then it expects a Primitive<T> specialization
struct DefaultResolver
{
// used to calculate IsReflected meta-function
template<class T> static char func(decltype(&T::Reflection));
template<class T> static int func(...);
template<class T>
struct IsReflected
{
enum
{
value = (sizeof(func<T>(nullptr)) == sizeof(char))
};
};
// get the TypeDescriptor for a reflected class
template<class T, typename std::enable_if<IsReflected<T>::value, int>::value = 0>
static TypeDescriptor* get()
{
return &T::Reflection;
}
// get the TypeDescriptor for a Primitive<T> if it is not reflected
template<class T, typename std::enable_if<!IsReflected<T>::value, int>::value = 0>
static TypeDescriptor* get()
{
return &Primitive<T>::Instance;
}
};
// helper class that provides type-safe access to a type's TypeDescriptor
template<class T>
struct TypeResolver
{
static TypeDescriptor* get()
{
return DefaultResolver::get<T>();
}
};
int main()
{
// no problems here, obviously
TypeDescriptor* desc = &Primitive<int>::Instance;
// resolves to false, as expected
constexpr bool isIntReflected = DefaultResolver::IsReflected<int>::value;
// resolves to true, as expected
constexpr bool isClassReflected = DefaultResolver::IsReflected<ReflectedType>::value;
// this does not compile
desc = TypeResolver<int>::get();
getchar();
return 0;
}
我 运行 在 TypeResolver<int>::get()
遇到问题,出现以下错误:
error C2672: 'DefaultResolver::get': no matching overloaded function found
note: while compiling class template member function 'TypeDescriptor *TypeResolver::get(void)'
note: see reference to function template instantiation 'TypeDescriptor *TypeResolver::get(void)' being compiled
note: see reference to class template instantiation 'TypeResolver' being compiled
error C2783: 'TypeDescriptor *DefaultResolver::get(void)': could not deduce template argument for '__formal'
note: see declaration of 'DefaultResolver::get'
第二个错误让我特别困惑。我正在指定模板参数,所以我缺少什么?
两个问题:
std::enable_if
没有 ::value
成员类型,只有条件为真时出现的 ::type
成员类型。
在 return DefaultResolver::get<T>()
中,提供显式模板参数会禁用这些参数的模板参数推导,这正是 std::enable_if
is depending on 工作的目的。
所以首先将 std::enable_if
声明中的 ::value
更改为 ::type
。下一个问题是在提供模板类型时允许模板参数推导工作。您可以通过将辅助模板作为函数参数传递来执行此操作,并在 DefaultResolver::get()
的声明中更改您的参数以接受该 class 类型的对象:
template <class T>
struct type_t { };
// ...
template <class T,
typename std::enable_if<IsReflected<T>::value, int>::type = 0>
static TypeDescriptor* get(type_t<T>);
template <class T,
typename std::enable_if<!IsReflected<T>::value, int>::type = 0>
static TypeDescriptor* get(type_t<T>);
// ...
template <class T>
struct TypeResolver
{
static TypeDescriptor* get()
{
return DefaultResolver::get(type_t<T>{});
}
};
希望这对您有所帮助。
我正在尝试用 C++ 编写我自己的简单反射系统。我有以下测试代码:
#include <cstdio>
#include <xtr1common>
// common base class
struct TypeDescriptor { };
// specialization for primitive types
template<class T>
struct Primitive : public TypeDescriptor
{
static Primitive<T> Instance;
};
Primitive<int> Primitive<int>::Instance;
struct ReflectedType
{
static TypeDescriptor Reflection;
};
// gets an appropriate TypeDescriptor for a type based on whether it has a Reflection member or not.
// if not, then it expects a Primitive<T> specialization
struct DefaultResolver
{
// used to calculate IsReflected meta-function
template<class T> static char func(decltype(&T::Reflection));
template<class T> static int func(...);
template<class T>
struct IsReflected
{
enum
{
value = (sizeof(func<T>(nullptr)) == sizeof(char))
};
};
// get the TypeDescriptor for a reflected class
template<class T, typename std::enable_if<IsReflected<T>::value, int>::value = 0>
static TypeDescriptor* get()
{
return &T::Reflection;
}
// get the TypeDescriptor for a Primitive<T> if it is not reflected
template<class T, typename std::enable_if<!IsReflected<T>::value, int>::value = 0>
static TypeDescriptor* get()
{
return &Primitive<T>::Instance;
}
};
// helper class that provides type-safe access to a type's TypeDescriptor
template<class T>
struct TypeResolver
{
static TypeDescriptor* get()
{
return DefaultResolver::get<T>();
}
};
int main()
{
// no problems here, obviously
TypeDescriptor* desc = &Primitive<int>::Instance;
// resolves to false, as expected
constexpr bool isIntReflected = DefaultResolver::IsReflected<int>::value;
// resolves to true, as expected
constexpr bool isClassReflected = DefaultResolver::IsReflected<ReflectedType>::value;
// this does not compile
desc = TypeResolver<int>::get();
getchar();
return 0;
}
我 运行 在 TypeResolver<int>::get()
遇到问题,出现以下错误:
error C2672: 'DefaultResolver::get': no matching overloaded function found
note: while compiling class template member function 'TypeDescriptor *TypeResolver::get(void)'
note: see reference to function template instantiation 'TypeDescriptor *TypeResolver::get(void)' being compiled
note: see reference to class template instantiation 'TypeResolver' being compiled
error C2783: 'TypeDescriptor *DefaultResolver::get(void)': could not deduce template argument for '__formal'
note: see declaration of 'DefaultResolver::get'
第二个错误让我特别困惑。我正在指定模板参数,所以我缺少什么?
两个问题:
std::enable_if
没有::value
成员类型,只有条件为真时出现的::type
成员类型。在
return DefaultResolver::get<T>()
中,提供显式模板参数会禁用这些参数的模板参数推导,这正是std::enable_if
is depending on 工作的目的。
所以首先将 std::enable_if
声明中的 ::value
更改为 ::type
。下一个问题是在提供模板类型时允许模板参数推导工作。您可以通过将辅助模板作为函数参数传递来执行此操作,并在 DefaultResolver::get()
的声明中更改您的参数以接受该 class 类型的对象:
template <class T>
struct type_t { };
// ...
template <class T,
typename std::enable_if<IsReflected<T>::value, int>::type = 0>
static TypeDescriptor* get(type_t<T>);
template <class T,
typename std::enable_if<!IsReflected<T>::value, int>::type = 0>
static TypeDescriptor* get(type_t<T>);
// ...
template <class T>
struct TypeResolver
{
static TypeDescriptor* get()
{
return DefaultResolver::get(type_t<T>{});
}
};
希望这对您有所帮助。