模板(元)编程总是只有一种实现方式吗?

iam*_*ind 0 c++ optimization templates metaprogramming

研究了一些template程序,特别是在编译时结果推导成常量的元程序,我了解到通常只有一种方法可以实现某些东西.例如:像factorial示例一样简单,或者像is_base_of一样复杂

我永远无法考虑具有完全不同逻辑的此类代码的完美替代实现.这是一个真实的假设吗?

如果这个假设是真的意味着,每当我们使用模板技巧实现某些东西时,我们总是确信,它是最好的代码,我们不必再担心优化编译时间了.

[注意:我没有提到我们template使用的一般用法class和功能.但用于推断编译时常量的用法.

Joh*_*mew 5

你倾向于只看到一种做事方式的原因是因为人们实际上使用模板元编程的东西通常在算法上是微不足道的 - 它们看起来很复杂,因为它们混淆了类型hackery的负载和奇怪的C++模板语法.

但有时候(正如Steve Jessop的回答所示)确实有多种算法来计算某些东西,你可以使用模板实现其中任何一种算法.

另一个例子,这里有两种评估方法pow(a,b)(对于小整数参数):

明显:

// ----- Simple Way -----

template <int A, int B>
struct PowA {
    typedef PowA<A,B-1> next;
    enum {
       value = A * next::value,
       recursion_count = 1 + next::recursion_count
    };
};
template <int A> struct PowA<A, 1> { enum { value = A, recursion_count = 0 }; };
template <int A> struct PowA<A, 0> { enum { value = 1, recursion_count = 0 }; };
Run Code Online (Sandbox Code Playgroud)

略显不明显:

// ----- Less Simple Way -----

template <int A, int B, int IsOdd> struct PowHelper;

template <int A> struct PowHelper<A, 0, 0> { enum { value = 1, recursion_count = 0 }; };
template <int A> struct PowHelper<A, 1, 1> { enum { value = A, recursion_count = 0 }; };

template <int A, int B>
struct PowHelper<A, B, 1> {
    typedef PowHelper<A, B-1, 1> next;
    enum {
        value = A * next::value,
        recursion_count = 1 + next::recursion_count
    };
};
template <int A, int B>
struct PowHelper<A, B, 0> {
    typedef PowHelper<A, B/2, ((B/2)&1)> next;
    enum {
        x = next::value,
        value = x*x,
        recursion_count = 1 + next::recursion_count
    };
};

template <int A, int B>
struct PowB {
    typedef PowHelper<A,B,(B & 1)> helper;
    enum {
        value = helper::value,
        recursion_count = helper::recursion_count
    };
};
Run Code Online (Sandbox Code Playgroud)

还有一些代码让你检查它:

// ----- Test -----

#include <iostream>

int main(int argc, char* argv[]) {
#define CHECK(X,Y) \
    std::cout << ("PowA: " #X "**" #Y " = ") << \
        PowA<(X),(Y)>::value << " (recurses " << \
        PowA<(X),(Y)>::recursion_count << " times)" << std::endl; \
    std::cout << ("PowB: " #X "**" #Y " = ") << \
        PowB<(X),(Y)>::value << " (recurses " << \
        PowB<(X),(Y)>::recursion_count << " times)" << std::endl;

    CHECK(3,3)
    CHECK(2,8)
    CHECK(7,3)
    CHECK(3,18)

#undef CHECK

   return 0;
}
Run Code Online (Sandbox Code Playgroud)