我想实现一个编译时foreach(),它可以调用给定的模板成员函数N次。 目前我有编译时的foreach:
struct ForEach
{
template <size_t Dummy>
struct IntToType {};
typedef IntToType<true> ForEachDoNotTerminateLoop;
typedef IntToType<false> ForEachTerminateLoop;
template <size_t TIdx, size_t TCount, typename TMethod>
static void ForEachImpl(ForEachDoNotTerminateLoop, TMethod method)
{
method.Invoke<TIdx>();
ForEachImpl<TIdx + 1, TCount, TMethod>(Internal::IntToType<(TIdx + 1 < TCount)>(), method);
}
template <size_t TIdx, size_t TCount, typename TMethod>
static void ForEachImpl(ForEachTerminateLoop, TMethod method)
{
}
template <size_t TCount, typename TMethod>
static void Member(TMethod method)
{
ForEachImpl<0, TCount, TMethod>(Internal::IntToType<(0 < TCount)>(), method);
}
};
还有一些模板类:
template <typename T, size_t TCount>
class SomeClass
{
public:
void Foo(int arg1)
{
ForEach::Member<TCount>(BarInvoker(this, arg1));
}
private:
struct BarInvoker // <-- How can I make this invoker a template to make it more flexible?
{
BarInvoker(SomeClass* instance, int arg1)
: instance(instance)
, arg1(arg1)
{}
template <size_t N>
void Invoke()
{
instance->Bar<N>(arg1);
}
int arg1;
SomeClass* instance;
};
template <size_t N>
void Bar(int arg1)
{
_data[N] = arg1;
}
int* _data;
T* _otherData;
};
有没有办法绕过“调用者”仿函数,使其更灵活(模板)并更容易使用?
我真的不喜欢通过为每个私有成员函数添加“调用者”存根来膨胀我的代码。
只需拨打ForEach::Member<TCount, int>(Bar, 5);
先谢谢你帮我解决这个模板的怪异! :)
答案 0 :(得分:4)
在类中包装模板函数并将类的实例传递给ForEach :: Call&lt;&gt;用任意参数来调用它,似乎是一个相当干净的解决方案。
ForEach::Call<>
的调用如下:ForEach::Call<N>(function_object, arguments...)
function_object
是一个定义为operator()
的类:
template <std::size_t Idx> // Current index in the for-loop.
void operator()(/* arguments... */) { /* Impl. */ }
这是我的ForEach&lt;&gt;版本。
class ForEach {
public:
/* Call function f with arguments args N times, passing the current index
through the template argument. */
template <std::size_t N, typename F, typename... Args>
static void Call(F &&f, Args &&...args) {
Impl<0, N>()(std::forward<F>(f), std::forward<Args>(args)...);
}
private:
/* Forward declaration. */
template <std::size_t Idx, std::size_t End>
class Impl;
/* Base case. We've incremeneted up to the end. */
template <std::size_t End>
class Impl<End, End> {
public:
template <typename F, typename... Args>
void operator()(F &&, Args &&...) { /* Do nothing. */ }
}; // Impl<End, End>
/* Recursive case. Invoke the function with the arguments, while explicitly
specifying the current index through the template argument. */
template <std::size_t Idx, std::size_t End>
class Impl {
public:
template <typename F, typename... Args>
void operator()(F &&f, Args &&...args) {
std::forward<F>(f).template operator()<Idx>(std::forward<Args>(args)...);
Impl<Idx + 1, End>()(std::forward<F>(f), std::forward<Args>(args)...);
}
}; // Impl<Idx, End>
}; // ForEach
我写了类似于你的SomeClass的东西,以证明它的用途。
template <std::size_t Size>
class Ints {
public:
using Data = std::array<int, Size>;
/* Call Assign, Size times, with data_ and n as the arguments. */
void AssignAll(int n) { ForEach::Call<Size>(Assign(), data_, n); }
/* Call Print, Size times, with data_ and n as the arguments. */
void PrintAll() const { ForEach::Call<Size>(Print(), data_); }
private:
/* Wraps our templated assign function so that we can pass them around. */
class Assign {
public:
template <size_t N>
void operator()(Data &data, int arg) const {
data[N] = arg;
}
}; // Assign
/* Wraps our templated print function so that we can pass them around. */
class Print {
public:
template <size_t N>
void operator()(const Data &data) const {
std::cout << data[N] << std::endl;
}
}; // Print
/* Our data. */
Data data_;
}; // Ints<Size>
Ints类的简单用例。
int main() {
Ints<5> ints;
ints.AssignAll(101);
ints.PrintAll();
}
打印:
101
101
101
101
101