Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/jenkins/5.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++_C++14_Template Meta Programming_Typetraits - Fatal编程技术网

C++ 为参数顺序不同的模板类创建比较特征 更新

C++ 为参数顺序不同的模板类创建比较特征 更新,c++,c++14,template-meta-programming,typetraits,C++,C++14,Template Meta Programming,Typetraits,可以找到我对T.C.答案的全功能实现 问题: 我正在写一个单位转换库。它目前只是标题,没有依赖项,如果可能的话,我想保留它 在库中,复合单位定义为简单单位的模板: template<class... Units> struct compound_unit { //...}; 当然,C++在一般情况下永远不能假定模板参数在不同的顺序中会表示相同的类型,所以我想知道是否有可能做出这样的特性,如果是的话,如何实现它。 奖励积分 我可以将复合单位限制为仅由简单单位类型组成,但如果我从简单单

可以找到我对T.C.答案的全功能实现

问题: 我正在写一个单位转换库。它目前只是标题,没有依赖项,如果可能的话,我想保留它

在库中,复合单位定义为简单单位的模板:

template<class... Units>
struct compound_unit { //...};

当然,C++在一般情况下永远不能假定模板参数在不同的顺序中会表示相同的类型,所以我想知道是否有可能做出这样的特性,如果是的话,如何实现它。 奖励积分

我可以将
复合单位
限制为仅由简单单位类型组成,但如果我从简单单位和其他复合单位混合组成
复合单位
,模板仍然可以工作(如果我有正确的特征,我库的其余部分已经可以处理这种情况)。如果性状也能分解嵌套的复合单位,并且仍然比较等价性,那将是一种更酷的方式

例如:

struct acceleration_1 : compound_unit<meters_per_second, inverse<second>> {};
struct acceleration_2 : compound_unit<meters, inverse<second>, inverse<second>> {};
结构加速1:复合单元{}; 结构加速_2:复合_单元{};
除非我误解了这个问题,否则您需要检查两个类型列表是否彼此相等,这与类型的顺序无关

例如:

<int, char> /*is equal to*/ <char, int>
<int, float, char> /*is equal to*/ <char, int, float>

这里有一个解决方案,我认为它符合您的要求,尽管有些地方不太好

代码如下:

#include <iostream>
#include <string>

#define METERS  1
#define SECONDS 3
#define INV     5

// ------- Start Unroll
// Unroll calculates the value of a compound type
template <typename... Type>
struct Unroll;

template <typename Type1, typename... Types> 
struct Unroll<Type1,Types...> {
    static constexpr int value = Type1::value * Unroll<Types...>::value;
};

template <typename Type>
struct Unroll<Type> {
    static constexpr int value = Type::value;
};

template <>
struct Unroll<> {
    static constexpr int value = 1;
};

// ---------- End Unroll

// Same definitions as in the question

template <typename... Units>
struct compound_unit {
    static constexpr int value = Unroll<Units...>::value;
};

struct meters {
    static constexpr int value = METERS;
};

struct seconds {
    static constexpr int value = SECONDS;
};

template <typename Unit>
struct inverse {
    // The -1 here can be anything, so long as is doesn't result in any of values which are defined at the top
    static constexpr int value = Unit::value * INV;
};

struct mps : compound_unit<meters, inverse<seconds>> {};
struct mps2 : compound_unit<inverse<seconds>, meters> {};

// Does the conversion using the Unroll struct to check that values are the same
template <typename T, typename V>
struct comparison_trait {
    static constexpr bool value = (T::value == V::value);
};

// Update for Bonus:

struct acc : compound_unit<mps, inverse<seconds>> {};
struct acc2 : compound_unit<meters, inverse<seconds>, inverse<seconds>> {};    

int main()
{
    bool check = comparison_trait<mps, mps2>::value;
    std::cout << "MPS check : " << check;

    bool check1 = comparison_trait<acc, acc2>::value;
    std::cout << "ACC check : " << check1;    
}
#包括
#包括
#定义仪表1
#定义秒数3
#定义库存5
//------开始展开
//展开计算复合类型的值
模板
结构展开;
模板
结构展开{
静态constexpr int value=Type1::value*Unroll::value;
};
模板
结构展开{
静态constexpr int value=Type::value;
};
模板
结构展开{
静态constexpr int值=1;
};
//------端部展开
//与问题中的定义相同
模板
结构复合单元{
静态constexpr int value=Unroll::value;
};
结构仪表{
静态constexpr int值=米;
};
结构秒{
静态constexpr int值=秒;
};
模板
结构逆{
//这里的-1可以是任何值,只要它不产生在顶部定义的任何值
静态constexpr int value=Unit::value*INV;
};
结构mps:复合单位{};
结构mps2:复合_单元{};
//转换是否使用展开结构检查值是否相同
模板
结构比较{
静态constexpr bool value=(T::value==V::value);
};
//奖金更新:
结构acc:component_unit{};
结构acc2:复合单元{};
int main()
{
bool check=比较特征::值;

std::cout
是O(N^2),当你唯一能做的就是比较是否相等时,加上它不能处理你的其他用例。因为只有这么多的SI基本单位,一个更好的方法是规范化你的单位

模板参数表示指数的通用SI单位类:

template<class Meter, class Kilogram, class Second,
         class Ampere, class Kelvin, class Candela, class Mole>
struct unit {};
模板
结构单元{};
乘以两个单位:

template<class, class> struct unit_multiply_impl;
template<class... Exps1, class... Exps2>
struct unit_multiply_impl<unit<Exps1...>, unit<Exps2...>> {
    using type = unit<std::ratio_add<Exps1, Exps2>...>;
};

template<class U1, class U2>
using unit_multiply = typename unit_multiply_impl<U1, U2>::type;
template struct unit\u multiply\u impl;
模板
结构单元\u乘法\u impl{
使用类型=单位;
};
模板
使用unit\u multiply=typename unit\u multiply\u impl::type;
反向:

template<class U> struct inverse_impl;
template<class... Exps>
struct inverse_impl<unit<Exps...>> {
    using type = unit<std::ratio_multiply<Exps, std::ratio<-1>>...>;
};

template<class U> using inverse = typename inverse_impl<U>::type;
template struct inverse\u impl;
模板
结构逆运算{
使用类型=单位;
};
使用inverse=typename inverse\u impl::type的模板;
复合=将它们全部相乘:

template<class U, class... Us> struct compound_impl;
template<class U> struct compound_impl<U> { using type = U; };
template<class U1, class U2, class...Us>
struct compound_impl<U1, U2, Us...>
    :  compound_impl<unit_multiply<U1, U2>, Us...> {};

template<class U, class... Us>
using compound_unit = typename compound_impl<U, Us...>::type;
template struct composite\u impl;
模板结构复合_impl{using type=U;};
模板
复合结构
:化合物_impl{};
模板
使用composite_unit=typename composite_impl::type;
测试:

using std::ratio;
using meters = unit<ratio<1>, ratio<0>, ratio<0>, ratio<0>, ratio<0>, ratio<0>, ratio<0>>;
using seconds = unit<ratio<0>, ratio<0>, ratio<1>, ratio<0>, ratio<0>, ratio<0>, ratio<0>>;

using mps = compound_unit<meters, inverse<seconds>>;
using mps = compound_unit<inverse<seconds>, meters>;

using acc = compound_unit<mps, inverse<seconds>>;
using acc = compound_unit<meters, inverse<seconds>, inverse<seconds>>;
使用std::ratio;
使用仪表=单位;
使用秒=单位;
使用mps=复合单位;
使用mps=复合单位;
使用acc=复合单位;
使用acc=复合单位;

这种方法的一大好处是,
composite\u unit
composite\u unit
实际上是同一个类型。

如果您可以提供类型的比较器,您可以对它们进行排序和相等性检查。我假设您已经简化了类似
composite\u unit
@Jarod42的情况。是的,我正在尝试解决这个问题一般的变量情况下,单位可能由5或6个其他东西组成,或者也可能由其他
复合单位组成。我知道你说过你不愿意在对答案的评论中使用boost…但是boost实际上有一个维度分析库,它似乎正是你想要做的。它可能是o其中一个库也是只实现为标头的…我忘了。只有这么多的SI基本单位。我会将其规范化为规范序列。我会尝试复制它。现在我的库只实现标头,没有依赖项,所以我不愿意使用任何增强。这是你要找的吗?我没有100%的信心理解q完全重复。此解决方案基本上检查两个类型列表是否相等,而不考虑排序。(检查编辑的答案)。是的,你对这个问题的理解是正确的。不过我的另一条评论仍然有效。@NicolasHolthaus:Boost。Hana本身没有依赖性,甚至与Boost的其他部分都没有依赖性。因此,如果这有什么不同的话,它是一个非常轻的依赖性。我来试一试。我的模板代码已经是如此递归和不可读,所以它不是一个大的代码al.@NicolasHolthaus,在演示中添加了一个链接,这样你就可以搞乱它了。希望它能做你想做的事。我可以看到的另一个缺点是,在有很多单位的情况下,乘以的ID可能会变得模棱两可,即1*4==4和2*2==4。没想到这一点,我会尝试想出一个解决方案。编译时哈希函数可以解决p问题,那么散列(1)*散列(4)!=散列(2)*散列(2),这会有帮助吗?我看到的使用
std::ratio
的问题是
template<class U> struct inverse_impl;
template<class... Exps>
struct inverse_impl<unit<Exps...>> {
    using type = unit<std::ratio_multiply<Exps, std::ratio<-1>>...>;
};

template<class U> using inverse = typename inverse_impl<U>::type;
template<class U, class... Us> struct compound_impl;
template<class U> struct compound_impl<U> { using type = U; };
template<class U1, class U2, class...Us>
struct compound_impl<U1, U2, Us...>
    :  compound_impl<unit_multiply<U1, U2>, Us...> {};

template<class U, class... Us>
using compound_unit = typename compound_impl<U, Us...>::type;
using std::ratio;
using meters = unit<ratio<1>, ratio<0>, ratio<0>, ratio<0>, ratio<0>, ratio<0>, ratio<0>>;
using seconds = unit<ratio<0>, ratio<0>, ratio<1>, ratio<0>, ratio<0>, ratio<0>, ratio<0>>;

using mps = compound_unit<meters, inverse<seconds>>;
using mps = compound_unit<inverse<seconds>, meters>;

using acc = compound_unit<mps, inverse<seconds>>;
using acc = compound_unit<meters, inverse<seconds>, inverse<seconds>>;