Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.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++ Constexpr与模板元编程-性能差异_C++_Metaprogramming_Template Meta Programming_Constexpr_Compile Time - Fatal编程技术网

C++ Constexpr与模板元编程-性能差异

C++ Constexpr与模板元编程-性能差异,c++,metaprogramming,template-meta-programming,constexpr,compile-time,C++,Metaprogramming,Template Meta Programming,Constexpr,Compile Time,我可以看到constexpr正在赢得越来越多的领域,它使用于模板元编程TMP的理由之一是性能。我的问题是: 在这方面是否有绩效比较的例子 如果更好,为什么不用constexpr替换TMP呢 TMP保证它在编译时运行,但这也可以通过constexpr实现。Constexpr处理浮点数,而TMP不处理浮点数。在我所看到的所有示例中,替换TMP的Constexpr函数更易于阅读,并且使用的代码行更少。constexpr还允许条件和循环,而TMP只处理循环的递归模拟 我在这里问了一个相关的问题——我有3

我可以看到constexpr正在赢得越来越多的领域,它使用于模板元编程TMP的理由之一是性能。我的问题是:

在这方面是否有绩效比较的例子

如果更好,为什么不用constexpr替换TMP呢

TMP保证它在编译时运行,但这也可以通过constexpr实现。Constexpr处理浮点数,而TMP不处理浮点数。在我所看到的所有示例中,替换TMP的Constexpr函数更易于阅读,并且使用的代码行更少。constexpr还允许条件和循环,而TMP只处理循环的递归模拟

我在这里问了一个相关的问题——我有3种不同的元编程方法——这里首选constexpr函数方式。

constexpr函数通常更具可读性,因为它们是常规函数

注意,即使在调用站点使用编译时常量参数,也可以在运行时使用它

constexpr int f(int n) { /*...*/ }

constexpr int f5 = f(5); // Compile time.
int f4 = f(4); // Runtime time (compiler can optimize as for non-constexpr functions though)
对于运行时性能,在常量表达式中使用时会出现类似的情况,因为所有操作都是在编译时完成的

对于编译时性能,TMP的问题是实例化的数量,而带有正则参数的constexpr函数通常使用较少的实例化,因此TMP通常使编译更长

但是,如果需要使用递归实现的斐波那契函数,则需要进行记忆

constexpr std::size_t fibonacci(std::size_t n)
{
    if (n < 2) return 1;
    return fibonacci(n - 1) + fibonacci(n - 2);
}
而constexpr则需要decltype和/或std::declval


关于第三种备选方案的建议:3。为什么不根据情况混合使用TMP和constexpr呢?@max66这不是我在我的一个例子中所做的吗?不过,从我所看到的情况来看,与TMP或TMP与constexpr混合使用相比,我仍然认为constexpr函数更可取。@badaboomskey:如果更好,为什么不用constexpr替换TMP呢?C++委员会正在努力做到这一点。但是constexpr编码目前还不如TMP强大。@badaboomskey:像阶乘计算这样的例子只是玩具。TMP主要用于进行类型计算。TMP允许tuple_元素从tuple类型中提取其中一种类型。纯constexpr代码不能做到这一点;您可以构建一个constexpr接口来进行类型计算,但这项工作的主要内容将以某种形式的TMP进行。constexpr的优势主要是代码可读性,并在某些情况下减少了ex的编译器开销。典型的编译时阶乘可能比递归模板花费更少的编译时间。等效代码应该具有类似的性能,除非您有严重的性能问题,否则您应该使用任何使代码更易于阅读的方法。如果例如,对于常规或constexpr函数中的类型,删除完整的专用模板函数,那么constexpr又如何呢-@克劳斯:constexpr if不适用于旧的TMP。这似乎是OP的问题。它可以避免使用可能复杂的SFINAE创建重载函数。不确定编译时性能是否有很大差异。我想说的是:目前有很多方法可以处理编译时代码生成。有带SFINAE的纯模板,有constexpr函数,可能有重载,但也有constexpr if。所有这三个部分都可以使用和混合,很难说在代码速度、质量、编译时间和所有其他方面什么是最好的。一如既往:如果您有疑问:度量:-我只是错过了constexpr If,因为您可以用一个包含constexpr If的模板替换任何递归模板专门化。简单地说。@Klaus:如果你这样做的话,还有一个变量模板,它同时适用于TMP和constexpr函数以及折叠它们的方式,递归方式和C++17折叠方式之间有区别。
template <std::size_t N> struct Fibonacci
{
    constexpr std::size_t value = Fibonacci<N - 2>::value + Fibonacci<N - 1>::value;
};
template <> struct Fibonacci<0>
{
    constexpr std::size_t value = 1;
};
template <> struct Fibonacci<1>
{
    constexpr std::size_t value = 1;
};
template <typename T> struct add_pointer
{
    using type = T*;
};

using int_ptr = add_pointer<int>::type;
template <typename T> struct Tag { using type = T; };
constexpr Tag<T*> add_pointer(Tag<T>) {return {}; }

using int_ptr = decltype(add_pointer(Tag<int>{})::type;