【问题标题】:C++98 get result of promotion from operatorC ++ 98从运算符获取提升结果
【发布时间】:2014-04-15 13:55:09
【问题描述】:

Type traits to get result of promotion from operator

对此的后续问题是否有一种仅使用 C++98 不提升的好方法?

【问题讨论】:

    标签: c++ templates


    【解决方案1】:

    只要你只需要关心标准的内置类型,你就可以这样做:

    template <int> struct plus_helper;
    template <> struct plus_helper< 1> { typedef char type; };
    template <> struct plus_helper< 2> { typedef signed char type; };
    template <> struct plus_helper< 3> { typedef unsigned char type; };
    template <> struct plus_helper< 4> { typedef short type; };
    template <> struct plus_helper< 5> { typedef unsigned short type; };
    template <> struct plus_helper< 6> { typedef int type; };
    template <> struct plus_helper< 7> { typedef unsigned int type; };
    template <> struct plus_helper< 8> { typedef long type; };
    template <> struct plus_helper< 9> { typedef unsigned long type; };
    template <> struct plus_helper<10> { typedef float type; };
    template <> struct plus_helper<11> { typedef double type; };
    template <> struct plus_helper<12> { typedef long double type; };
    template <> struct plus_helper<13> { typedef wchar_t type; };
    
    template <typename T1, typename T2>
    struct plus {
    private:
      static char (&f(char))[1];
      static char (&f(signed char))[2];
      static char (&f(unsigned char))[3];
      static char (&f(short))[4];
      static char (&f(unsigned short))[5];
      static char (&f(int))[6];
      static char (&f(unsigned int))[7];
      static char (&f(long))[8];
      static char (&f(unsigned long))[9];
      static char (&f(float))[10];
      static char (&f(double))[11];
      static char (&f(long double))[12];
      static char (&f(wchar_t))[13];
    public:
      typedef typename plus_helper<sizeof(f(*(T1*)0 + *(T2*)0))>::type type;
    };
    
    template <typename T1, typename T2>
    struct plus<T1 *, T2> {
      typedef T1 *type;
    };
    
    template <typename T1, typename T2>
    struct plus<T1, T2 *> {
      typedef T2 *type;
    };
    

    请注意,我要求可以添加 T1T2。如果它们不可能,则不一定会给出错误。另请注意,我没有省略比int 更短的类型。内置的+ 运算符永远无法返回它们,但它们是自定义operator+ 的有效返回类型。

    不幸的是,如果您还需要担心其他类型,例如自定义结构,那么这种方法将不起作用,虽然我很乐意被证明是错误的,但我认为不可能做到这一点工作。

    【讨论】:

    【解决方案2】:

    可能不是最好的方法,但这就是我得到的......

    template <bool value,typename T,typename J>
    struct conditional{typedef T type;};
    
    template <typename T,typename J>
    struct conditional<false,T,J>{typedef J type;};
    
    template <typename T, typename J>
    struct is_equal
    {
      enum {value = false};
    };
    
    template <typename T>
    struct is_equal<T,T>
    {
      enum {value = true};
    };
    
    namespace
    {
    template <typename T, typename J, typename K, typename L>
    struct math_t
    {
      typedef typename conditional<
        is_equal<T,K>::value || is_equal<J,K>::value,
        K,
        L>::type type;
    };
    }
    template <typename T, typename J>
    struct math_type
    {
      typedef typename math_t<T,J,long double,
      typename math_t<T,J,double,
      typename math_t<T,J,float,
      typename math_t<T,J,long long unsigned int,
      typename math_t<T,J,long long int,
      typename math_t<T,J,long unsigned int,
      typename math_t<T,J,long int,
      typename math_t<T,J,unsigned int,
      int>::type>::type>::type>::type>::type>::type>::type>::type type;
    };
    

    【讨论】:

    • 考虑添加long intunsigned int 时会发生什么。结果取决于实现,但在我的系统上,它是unsigned long int,这不是您的模板提供的。
    【解决方案3】:

    我在这里讨论了一个类似的问题:https://stackoverflow.com/a/2450157/34509。重新粘贴我的代码,因为这似乎是您所追求的。详细解释请看参考答案

    // typedef eiher to A or B, depending on what integer is passed
    template<int, typename A, typename B>
    struct cond;
    
    #define CCASE(N, typed) \
      template<typename A, typename B> \
      struct cond<N, A, B> { \
        typedef typed type; \
      }
    
    CCASE(1, A); CCASE(2, B);
    CCASE(3, int); CCASE(4, unsigned int);
    CCASE(5, long); CCASE(6, unsigned long);
    CCASE(7, float); CCASE(8, double);
    CCASE(9, long double);
    
    #undef CCASE
    
    // for a better syntax...
    template<typename T> struct identity { typedef T type; };
    
    // different type => figure out common type
    template<typename A, typename B>
    struct promote {
    private:
      static A a;
      static B b;
    
      // in case A or B is a promoted arithmetic type, the template
      // will make it less preferred than the nontemplates below
      template<typename T>
      static identity<char[1]>::type &check(A, T);
      template<typename T>
      static identity<char[2]>::type &check(B, T);
    
      // "promoted arithmetic types"
      static identity<char[3]>::type &check(int, int);
      static identity<char[4]>::type &check(unsigned int, int);
      static identity<char[5]>::type &check(long, int);
      static identity<char[6]>::type &check(unsigned long, int);
      static identity<char[7]>::type &check(float, int);
      static identity<char[8]>::type &check(double, int);
      static identity<char[9]>::type &check(long double, int);
    
    public:
      typedef typename cond<sizeof check(0 ? a : b, 0), A, B>::type
        type;
    };
    
    // same type => finished
    template<typename A>
    struct promote<A, A> {
      typedef A type;
    };
    

    例如

    int main() {
      promote<char, short>::type a;
      int *p0 = &a;
    
      promote<float, double>::type b;
      double *p1 = &b;
    
      promote<char*, string>::type c;
      string *p2 = &c;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-11
      • 1970-01-01
      • 2011-03-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多