使用模板从类型列表中提升类型

时间:2013-04-23 12:05:23

标签: c++ templates c++11

我有一个带有int元素的向量和一个带有float元素的向量。 在这种情况下,大多数优先类型是浮点数,在点积中我想返回一个浮点类型(如果没有指定)。

以下代码就是这样做的,但模板包出了问题。

我能得到一些帮助吗?

#include <iostream>
#include <vector>
#include <array>
using namespace std;


template<typename Tp, typename T1> struct contains
{
    constexpr static bool value = std::is_same<Tp, T1>::value;
};
template<typename Tp, typename T1, typename ... Tn> struct contains
{
    constexpr static bool value = std::is_same<Tp, T1>::value || contains<Tp, Tn...>::value;
};

template<typename ... T> struct perfect
{
    typedef 
        typename std::conditional<contains<long double, T...>::value, long double,
        typename std::conditional<contains<double     , T...>::value, double,
        typename std::conditional<contains<float      , T...>::value, float,
        typename std::conditional<contains<long long  , T...>::value, long long,
        typename std::conditional<contains<unsigned long long, T...>::value, unsigned long long,
        typename std::conditional<contains<int        , T...>::value, int,
        typename std::conditional<contains<unsigned int, T...>::value, unsigned int,
        //.....
        void
        >>>>>>>::type type;
};


struct Vector1 : public std::vector<double> {};
struct Vector2 : public std::vector<int> {};
struct Vector3 : public std::vector<float> {};

template<typename C1, typename C2, typename T = perfect<typename C1::value_type, typename C2::value_type>::type>
T dot_product(const C1 &c1, const C2 &c2)
{
    return 0; // return c1 * c2
} 

int main()
{
    Vector1 a;
    Vector2 b;
    cout << dot_product(a, b) << endl;
    cout << dot_product<Vector1, Vector2, long double>(a, b) << endl;
}

3 个答案:

答案 0 :(得分:2)

你在这里缺少两件事。

template<typename Tp, typename T1> struct contains
{
    constexpr static bool value = std::is_same<Tp, T1>::value;
};

专业化所以它应该是

template<typename Tp, typename T1> struct contains<T1,Tp>
                                               // ^^^^^^ 
{
    constexpr static bool value = std::is_same<Tp, T1>::value;
};

,应在原始模板之后定义


接下来你在这里缺少类型名称。

template<typename C1, typename C2, typename T = typename perfect<typename C1::value_type, typename C2::value_type>::type>
                                             // ^^^^^^^ 

但是我应该提一下,你可能在这里过于复杂。我不确定是否所有这些都是从两种类型中扣除所必需的。也许预处理器宏可以为您做得更好。我假设这是一个练习。



修改
 OK这是一个类似的操作,但与C++ Templates a Complete Guide的方法不同。虽然旧但仍足以满足您的需求

#define MK_PROMOTION(T1,T2,Tr)             \
    template<> class Promotion<T1, T2> {   \
      public:                              \
        typedef Tr type;                   \
    };                                     \
                                           \
    template<> class Promotion<T2, T1> {   \
      public:                              \
        typedef Tr type;                   \
    };



template<typename T1, typename T2>
class Promotion {
public:
    typedef T1 type;    
};


template<typename T>
class Promotion<T,T> {
  public:
    typedef T type;
};

MK_PROMOTION(int, char, int)
MK_PROMOTION(double, float, double)
MK_PROMOTION(double, int, double)




typedef std::vector<double> Vector1;
typedef std::vector<int> Vector2;
typedef std::vector<float> Vector3;


template<typename C1, typename C2, typename T = typename Promotion< typename C1::value_type, typename C2::value_type >::type >
T dot_product(const C1 &c1, const C2 &c2)
{
    return 0; // return c1 * c2
} 

int main()
{
    Vector1 a;
    Vector2 b;
    cout << dot_product(a, b) << endl;
    cout << dot_product<Vector1, Vector2, long double>(a, b) << endl;
}

答案 1 :(得分:1)

您正在寻找decltype<C1() * C2()>,不需要struct perfect

答案 2 :(得分:0)

编辑: decltype()做得更好。

template<typename C1, typename C2, typename T = decltype(typename C1::value_type() * typename C2::value_type())>
T dot_product(const C1 &c1, const C2 &c2) { return 5; }

针对未来社区需求的固定程序:(许多语法错误)

#include <iostream>
#include <vector>
using namespace std;

template<typename Tp, typename T1, typename ... Tn> struct contains_type
    { constexpr static bool value = std::is_same<Tp, T1>::value || contains_type<Tp, Tn...>::value; };
template<typename Tp, typename T1> struct contains_type<Tp, T1>
    { constexpr static bool value = std::is_same<Tp, T1>::value; };

template<typename ... T> struct type_promotion
{
    typedef typename
        std::conditional<contains_type<long double, T...>::value, long double,
        typename std::conditional<contains_type<double     , T...>::value, double,
        typename std::conditional<contains_type<float      , T...>::value, float,
        typename std::conditional<contains_type<long long  , T...>::value, long long,
        typename std::conditional<contains_type<unsigned long long, T...>::value, unsigned long long,
        typename std::conditional<contains_type<int        , T...>::value, int,
        typename std::conditional<contains_type<unsigned int, T...>::value, unsigned int,
        void>::type>::type>::type>::type>::type>::type>::type type;
};


struct Vector1 : public std::vector<double> {};
struct Vector2 : public std::vector<int> {};

template<typename C1, typename C2, typename T = typename type_promotion<typename C1::value_type, typename C2::value_type>::type>
T dot_product(const C1 &c1, const C2 &c2)
    { return 5; } 

int main()
{
    Vector1 a;
    Vector2 b, c;
    cout << dot_product(a, b) / 2 << endl;
    cout << dot_product(b, c) / 2 << endl;
    cout << dot_product<Vector1, Vector2, long double>(a, b) << endl;
}