我正在实现一个泛型类,对于不同的类型集(不仅对于不同的离散类型),它的行为应该不同。目标是序列化不同类型的对象以通过自定义协议发送它们(但这是更多的教育任务而不是实用的东西;我是一个对分布式计算感兴趣的学生)。例如,我需要以不同的方式发送浮点数和整数。我还想拥有其他 POD 类型的默认处理程序。但我需要覆盖我的一些 POD 类型的行为......
我发现 SFINAE 方法非常有用,并为使用 SFINAE 原则和部分专业化的自定义类型实现了整数和浮点类型的泛型类(参见下面的代码)。但是,当我尝试实现其他 POD 类型的处理程序并希望其他处理程序与更通用的 POD 类型处理程序重叠时,我遇到了一个模棱两可的问题。实际上,我的 GenericObject 类的 POD 类型及其子集(整数和浮点类型)的可能特化没有重叠。
我试图实现专业化的手动排序,阅读了很多关于部分排序的信息,如果一个专业化更专业,那么它比另一个专业化更受欢迎。但我没能解决问题。我不知道如何以手动方式消除我的部分专业化歧义。
排除我的 POD 类型处理程序的一组浮点类型和整数类型的解决方案对我来说是不可接受的,因为这种方式会在处理程序之间产生过多的依赖关系。我希望有一个正确的方法来解决我的问题。例如,在程序开始时,所有静态资源都被初始化为几个优先级。在 GCC 中,我可以使用属性构造函数控制这种初始化的顺序:__attribute__((constructor(101))) 或类似的属性 init_priority。如果我能以这种方式重新排序模板部分专业化,我会很高兴。
你能给我什么建议吗?
这是我的代码:
#include <type_traits>
#include <iostream>
#include <cxxabi.h>
// General form
template <typename T, typename Enable0 = void>
struct GenericObject {
char * description() {
return (char *)"Undefined";
}
};
// Specialization for integral types
template <typename T>
struct GenericObject<T, typename std::enable_if<std::is_integral<T>::value>::type> {
char * description() {
return (char *)"Integral";
}
};
// Specialization for real types
template <typename T>
struct GenericObject<T, typename std::enable_if<std::is_floating_point<T>::value>::type> {
char * description() {
return (char *)"Real";
}
};
// Specialization for other POD types. It MUST be less specialized than specializations for real and integral types, because in other way there will be an ambiguity, because every integral type is also a POD.
/*
HERE IS MY PROBLEM
*/
template <typename T>
struct GenericObject<T, typename std::enable_if<std::is_pod<T>::value>::type> {
char * description() {
return (char *)"POD";
}
};
// Declaration of types
struct IAmDefined {};
struct IAmUndefinedPOD {};
struct IAmUndefinedComplexClass : virtual IAmUndefinedPOD {};
// Specialization for IAmDefined class and also the most specialized template specialization.
template <>
struct GenericObject<IAmDefined> {
char * description() {
return (char *)"Defined";
}
};
// Produces nice output
std::string demangle(const char *raw) {
int status;
char *demangled = abi::__cxa_demangle(raw, 0, 0, &status);
std::string result(demangled);
free(demangled);
return result;
}
template <typename T>
void testObject() {
GenericObject<T> object;
std::cout << demangle(typeid(T).name()) << ": " << object.description() << std::endl;
}
int main() {
testObject<int>(); // Integral
testObject<long>(); // Integral
testObject<float>(); // Real
testObject<double>(); // Real
testObject<void>(); // POD
testObject<IAmDefined>(); // Defined
testObject<IAmUndefinedPOD>(); // POD
testObject<IAmUndefinedComplexClass>(); // Undefined
}
这是编译时错误:
g++ --std=c++11 main.cc -o specialization-of-sets
main.cc: In instantiation of 'void testObject() [with T = int]':
main.cc:85:21: required from here
main.cc:68:22: error: ambiguous class template instantiation for 'struct GenericObject<int, void>'
main.cc:15:8: error: candidates are: struct GenericObject<T, typename std::enable_if<std::is_integral<_Tp>::value>::type>
main.cc:36:8: error: struct GenericObject<T, typename std::enable_if<std::is_pod<_Tp>::value>::type>
main.cc:68:22: error: 'GenericObject<int, void> object' has incomplete type
main.cc: In instantiation of 'void testObject() [with T = long int]':
main.cc:86:22: required from here
main.cc:68:22: error: ambiguous class template instantiation for 'struct GenericObject<long int, void>'
main.cc:15:8: error: candidates are: struct GenericObject<T, typename std::enable_if<std::is_integral<_Tp>::value>::type>
main.cc:36:8: error: struct GenericObject<T, typename std::enable_if<std::is_pod<_Tp>::value>::type>
main.cc:68:22: error: 'GenericObject<long int, void> object' has incomplete type
main.cc: In instantiation of 'void testObject() [with T = float]':
main.cc:87:23: required from here
main.cc:68:22: error: ambiguous class template instantiation for 'struct GenericObject<float, void>'
main.cc:23:8: error: candidates are: struct GenericObject<T, typename std::enable_if<std::is_floating_point<_Tp>::value>::type>
main.cc:36:8: error: struct GenericObject<T, typename std::enable_if<std::is_pod<_Tp>::value>::type>
main.cc:68:22: error: 'GenericObject<float, void> object' has incomplete type
main.cc: In instantiation of 'void testObject() [with T = double]':
main.cc:88:24: required from here
main.cc:68:22: error: ambiguous class template instantiation for 'struct GenericObject<double, void>'
main.cc:23:8: error: candidates are: struct GenericObject<T, typename std::enable_if<std::is_floating_point<_Tp>::value>::type>
main.cc:36:8: error: struct GenericObject<T, typename std::enable_if<std::is_pod<_Tp>::value>::type>
main.cc:68:22: error: 'GenericObject<double, void> object' has incomplete type
我使用 GCC 4.8:
gcc 版本 4.8.0 20120314(实验性)[主干修订版 185382](Ubuntu/Linaro 20120314-0ubuntu2)
先感谢您。