3

我有一个参数包,里面装满了默认的可构造对象,然后是可调用对象(如ExampleFunctor),并希望按顺序调用所有对象(从左到右)。如果返回类型是 void 以外的任何内容,我可以使用初始化列表来执行此操作:

struct ExampleFunctor{
    void operator()(){someGlobal = 4;}
};

template<typename... Ts>
struct CallThem {
    void operator()(){
        auto list = {Ts()()...};
    }
}

但是,如果返回类型为 void,则此技巧不起作用。

我可以将所有 T 包装在一个返回 int 的包装器中,但这似乎有点过头了,而且这段代码最终将在具有 32K 闪存的 cortex M3 上运行,因此如果我在调试中编译单元,包装器的额外函数调用开销会很痛苦模式(并且在发布模式下调试让我的大脑受伤)。

有没有更好的办法?

4

3 回答 3

6

使用逗号运算符:

int someGlobal;

struct ExampleFunctor{
    void operator()(){someGlobal = 4;}
};

template<typename... Ts>
struct CallThem {
    void operator()(){
        int list[] = {(Ts()(),0)...};
        (void)list;
    }
};

int main()
{
    CallThem<ExampleFunctor, ExampleFunctor>{}();
}

顺便说一句,我在initializer_list这里使用的不是一个数组,而是一个数组;尝试一下编译器可以丢弃哪一个/如果有的话。这(void)list是为了抑制警告(未使用的变量)。

于 2013-11-08T14:09:07.987 回答
1

编译器应该能够优化掉这里的函数调用:

template <typename H, typename... Tail>
void call(H head, Tail... tail) {
   head();
   call(tail...);
}
template <typename T>
void call(T fn) {
   fn();
}
template <typename... Args>
void callThem() {
   call(Args()...);
}

但这是未经测试的。检查为您的平台生成的程序集。

于 2013-11-08T14:14:13.160 回答
0

你可以使用类似的东西:

template<typename... Ts>
struct CallThem;

template<>
struct CallThem<> { void operator()() const {} };

template<typename Tail, typename... Queue>
struct CallThem<Tail, Queue...>
{
    void operator()() const {
        Tail()();
        CallThem<Queue...>()();
    }
};
于 2013-11-08T14:17:10.227 回答