Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;:部分专业化的手动消歧(使用SFINAE)_C++_Templates_C++11_Template Specialization_Sfinae - Fatal编程技术网

C++ C++;:部分专业化的手动消歧(使用SFINAE)

C++ C++;:部分专业化的手动消歧(使用SFINAE),c++,templates,c++11,template-specialization,sfinae,C++,Templates,C++11,Template Specialization,Sfinae,我正在实现一个泛型类,它对于不同的类型集应该有不同的行为(不仅仅是对于不同的离散类型)。目标是序列化不同类型的对象,以便通过自定义协议发送它们(但这更像是一项教育任务,而不是一些实用的东西;我是一名对分布式计算感兴趣的学生)。例如,我需要以不同的方式发送浮点和整数。我还希望有一个其他POD类型的默认处理程序。但是我需要覆盖我的一些豆荚类型的行为 我发现SFINAE方法非常有用,它为整型和浮点型实现了泛型类,为使用SFINAE原理和部分专门化的自定义类型实现了泛型类(请参见下面的代码)。但当我试图

我正在实现一个泛型类,它对于不同的类型集应该有不同的行为(不仅仅是对于不同的离散类型)。目标是序列化不同类型的对象,以便通过自定义协议发送它们(但这更像是一项教育任务,而不是一些实用的东西;我是一名对分布式计算感兴趣的学生)。例如,我需要以不同的方式发送浮点和整数。我还希望有一个其他POD类型的默认处理程序。但是我需要覆盖我的一些豆荚类型的行为

我发现SFINAE方法非常有用,它为整型和浮点型实现了泛型类,为使用SFINAE原理和部分专门化的自定义类型实现了泛型类(请参见下面的代码)。但当我试图实现其他POD类型的处理程序,希望其他处理程序将与更一般的POD类型处理程序重叠时,我遇到了一个模棱两可的问题。实际上,对于POD类型和它的子集(整型和浮点型),我的GenericObject类的可能专门化没有重叠

我试图实现专业化的手动排序,读了很多关于偏序的书,关于一种专业化比另一种更专业化的专业化更受欢迎。但我没能解决这个问题。我不知道如何以手动方式消除我部分专业的歧义

排除POD类型处理程序的一组浮点类型和整数类型的解决方案对我来说是不可接受的,因为这种方式会在处理程序之间产生过多的依赖关系。我希望有一个正确的方法来解决我的问题。例如,在程序开始时,所有静态资源都用几个优先级初始化。在GCC中,我可以使用一个属性构造函数来控制这种初始化的顺序:uuuu属性_uuuu((构造函数(101)))或类似的属性init_优先级。我会很高兴,如果我可以重新排序模板部分专门化在这样的方式

你能给我提些建议吗

这是我的密码:

#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
}
#包括
#包括
#包括
//一般形式
模板
结构GenericObject{
char*description(){
返回(字符*)“未定义”;
}
};
//整型的专门化
模板
结构GenericObject{
char*description(){
返回(字符*)“整数”;
}
};
//实类型的专门化
模板
结构GenericObject{
char*description(){
返回(字符*)“真实”;
}
};
//其他豆荚类型的专门化。它的专业化程度必须低于实数和整型的专业化程度,因为从另一方面来说,会有歧义,因为每个整型也是一个POD。
/*
这是我的问题
*/
模板
结构GenericObject{
char*description(){
返回(字符*)“POD”;
}
};
//类型声明
结构定义{};
结构IAUNDEFINEDPOD{};
结构IAUNDEFINEDCOMPLEXCLASS:虚拟IAUNDEFINEDPOD{};
//IAM定义类的专门化,也是最专门化的模板专门化。
模板
结构GenericObject{
char*description(){
返回(字符*)“已定义”;
}
};
//产量可观
std::string demangle(const char*raw){
智力状态;
char*demangled=abi::_cxa_demangle(原始、0、0和状态);
std::字符串结果(demangled);
免费的(被要求的);
返回结果;
}
模板
void testObject(){
一般对象;

std::cout我个人会用重载而不是类模板部分专门化来解决这个问题。通过这种方式,您可以很容易地引入一个平局断路器:

template<class T> struct type{};

namespace detail{
template<class T> using Invoke = typename T::type;
template<class C, class T = void> using EnableIf = Invoke<std::enable_if<C::value, T>>;
template<class T> using EType = type<EnableIf<T>>;

// we need two tie-breakers here, one for general vs specialized case
// and one for specialized vs more specialized case
template<class T>
char const* describe(EType<std::is_integral<T>>, int, int){ return "Integral"; }
template<class T>
char const* describe(EType<std::is_floating_point<T>>, int, int){ return "Real"; }
template<class T>
char const* describe(EType<std::is_pod<T>>, int, long){ return "POD"; }
template<class T>
char const* describe(type<void>, long, long){ return "Undefined"; }
} // detail::

template<class T>
char const* describe(type<T>){
  // literal '0' is 'int', as such 'int' overloads are preferred
  return detail::describe<T>(type<void>(), 0, 0);
}

// ...

// simple overload for specialized types
char const* describe(type<IAmDefined>){
  return "Defined";
}
模板结构类型{};
名称空间详细信息{
使用Invoke=typename T::type的模板;
使用EnableIf=Invoke的模板;
模板使用EType=type;
//我们这里需要两个连接断路器,一个用于一般情况,另一个用于特殊情况
//一个是专门的,另一个是更专业的
模板
char const*descripe(EType,int,int){return“Integral”;}
模板
char const*descripe(EType,int,int){返回“Real”;}
模板
char const*descripe(EType,int,long){返回“POD”;}
模板
char const*descripe(type,long,long){返回“未定义”;}
}//详细信息::
模板
字符常量*描述(类型){
//文字“0”是“int”,因此首选“int”重载
返回详细信息::descripe(type(),0,0);
}
// ...
//专用类型的简单重载
字符常量*描述(类型){
返回“已定义”;
}

请注意,
void
属于
“未定义的”
类别,它不是一个POD。

我个人会用重载而不是类模板部分专门化来解决这个问题。通过这种方式,您可以很容易地引入一个绑定断路器:

template<class T> struct type{};

namespace detail{
template<class T> using Invoke = typename T::type;
template<class C, class T = void> using EnableIf = Invoke<std::enable_if<C::value, T>>;
template<class T> using EType = type<EnableIf<T>>;

// we need two tie-breakers here, one for general vs specialized case
// and one for specialized vs more specialized case
template<class T>
char const* describe(EType<std::is_integral<T>>, int, int){ return "Integral"; }
template<class T>
char const* describe(EType<std::is_floating_point<T>>, int, int){ return "Real"; }
template<class T>
char const* describe(EType<std::is_pod<T>>, int, long){ return "POD"; }
template<class T>
char const* describe(type<void>, long, long){ return "Undefined"; }
} // detail::

template<class T>
char const* describe(type<T>){
  // literal '0' is 'int', as such 'int' overloads are preferred
  return detail::describe<T>(type<void>(), 0, 0);
}

// ...

// simple overload for specialized types
char const* describe(type<IAmDefined>){
  return "Defined";
}
模板结构类型{};
名称空间详细信息{
使用Invoke=typename T::type的模板;
使用EnableIf=Invoke的模板;
模板使用EType=type;
//我们这里需要两个连接断路器,一个用于一般情况,另一个用于特殊情况
//一个是专门的,另一个是更专业的
模板
char const*descripe(EType,int,int){return“Integral”;}
模板
char const*descripe(EType,int,int){返回“Real”;}
模板
char const*descripe(EType,int,long){返回“POD”;}
模板
char const*descripe(type,long,long){返回“未定义”;}
}//详细信息::
模板
字符常量*描述(类型){
//文字“0”是“int”,因此首选“int”重载
返回详细信息::descripe(type(),0,0);
}
// ...
//专用类型的简单重载
字符常量*描述(类型){
返回“已定义”;
}

请注意,
void
属于
“未定义的”
类别,它不是一个POD。

我一直在使用std::enable\u if手动解决歧义,但当您有许多备选方案时,这种方法可能成为样板:

#include <iostream>
#include <type_traits>

using namespace std;

template<typename T>
const char* describe(T,
                     typename enable_if<is_integral<T>::value>::type* = 0)
{
    return "integral";
}

template<typename T>
const char* describe(T,
                     typename std::enable_if<is_floating_point<T>::value>::type* = 0)
{
    return "floating_point";
}

template<typename T>
const char* describe(T,
                     typename std::enable_if<!std::is_integral<T>::value && !std::is_floating_point<T>::value && std::is_pod<T>::value>::type* = 0)
{
    return "pod";
}
#包括
#包括
使用名称空间std;
模板
常量字符*描述(T,
typename启用(如果::type*=0)
{
返回“积分”;
}
模板
常量字符*描述(T,