1

以下简单的代码模式在图形编程中非常常见。
它创建一个层数组并在它们之上循环。

struct Layer
{
    int n;
    void operator()(float value)
    {
    }
};

struct AnotherLayer
{
    int n;
    int m;
    void operator()(float value)
    {
    }
};

void process_layers(Layer_t* layer, size_t size, float value) 
{
    for (size_t n = 0; n < size; ++n)
        layer[n](value);
}

Layer a = {1};
Layer b = {2};
AnotherLayer c = {2,3};
typedef std::function < void (float) > Layer_t;
Layer_t layers [] = {a,b,c};
process_layers(layers, sizeof(layers)/sizeof(Layer), 100);

我想将其转换为在 c++11 中使用可变参数模板。任何想法我怎么能做到这一点。这就是我希望它看起来的样子。有任何想法吗?这甚至可能吗?

template <int n>
struct Layer
{
    void operator()(float value)
    {
    }
};

template <int n, int m>
struct AnotherLayer
{
    void operator()(float value)
    {
    }
};

template <typename Layer1, typename Layer2, ...>
struct Layers  //process_layers
{
    void operator()(float value)
    {
        for (size_t n = 0; n < SIZEOF(Layer1,Layer2,...); ++n)
            Layer[N]()(value);
    }
};

然后我可以做到这一点。

typedef Layers<Layer<1>, Layer<2>, AnotherLayer<3,8> > funky_layer_t;
typedef Layers<Layer<4>, Layer<5>, Layer<5>, AnotherLayer<6,7> > standard_layer_t;
typedef Layers<funky_layer_t, standard_layer_t> awesome_layer_t;

awesome_layer_t()(100);

注意:使用第二种方法,构建层的所有参数在编译时都是已知的。

4

2 回答 2

1

您提供的示例非常简单,可以使用可变参数模板重做。

template<typename Func> void process(Func &&f) {} // base case for zero items

// overload for at least one item
template<typename Func, typename FirstItem, typename... Items>
void process(Func &&f, FirstItem &&fi, Items &&...is) {
    std::forward<Func>(f)(std::forward<FirstItem>(fi));          // f(fi);
    process(std::forward<Func>(f), std::forward<Items>(is)...);  // process(f,is...);
}

Layer a = {1};
Layer b = {2};
Layer c = {3};

process([](Layer &l){ l(100); },
        a, b, c);

另请注意,这避免了原件中所有不必要的副本。(当然你也可以通过这样做来避免它们Layer layers[] = {{1},{2},{3}};


我不确定您以后的评论和代码与在图层集合上运行操作有何关系。

您想在编译时执行的计算究竟是什么?


要针对新示例进行调整,process()根本不需要更改,您只需要创建一个可以处理每种类型的函子。(多态 lambda 在这里会有所帮助,但我们必须使用显式仿函数类型)

Layer a = {1};
Layer b = {2};
AnotherLayer c = {2,3};

struct TheOperation {
    template<typename T>
    void operator() (T &t) {
        t(100);
    }
};

process(TheOperation(),
    a, b, c);

这是您awesome_layer_t为正确可变参数模板语法而转录的内容,但我仍然看不到您想要完成什么,所以我不能说这是否是一个好方法。这实际上并没有operator()在编译时调用 s,它只是安排在运行时默认构造一堆对象,然后在运行时operator()再次调用。

template <int n>
struct Layer
{
    int operator()(float value)
    {
        std::printf("L %d %e\n",n,value);
        return 0;
    }
};

template <int n, int m>
struct AnotherLayer
{
    int operator()(float value)
    {
        std::printf("AL %d %d %e\n",n,m,value);
        return 0;
    }
};

template <typename... Ls>
struct Layers  //process_layers
{
    int operator()(float value)
    {
        struct Tmp {
            void operator() (...) {}
        };
        Tmp()( Ls()(value)...);
        return 0;
    }
};

typedef Layers<Layer<1>, Layer<2>, AnotherLayer<3,8> > funky_layer_t;
typedef Layers<Layer<4>, Layer<5>, Layer<5>, AnotherLayer<6,7> > standard_layer_t;
typedef Layers<funky_layer_t, standard_layer_t> awesome_layer_t;

int main() {
    awesome_layer_t()(100);
}
于 2012-06-21T20:18:02.330 回答
0

我相信你可以使用普通的函数模板来做到这一点,如下所示:

/* Base case: If you have no layers to apply, do nothing. */
void executeLayers() {
    // Deliberately empty.
}

/* Recursive step: If you have at least one layer, apply it, then apply the
 * remaining layers.
 */
template <typename Head, typename... Tail> 
void executeLayers(Head head, Tail... tail) {
    head();              // Execute the first layer
    executeLayers(tail); // Execute the remaining layers
}

然后你可以做这样的事情:

executeLayers(layer1, layer2, layer3, layer4, layer5);

希望这可以帮助!

于 2012-06-21T20:10:11.003 回答