可变参数模板的代码大小问题
Code size concerns with variadic templates
我正在创建一种算法,可以同时处理许多不同的用户定义类型。假定这些类型中的每一个都具有 func1
和 func2
,它们将成为 MyAlgorithm
的接口。我可以使用可变模板来做到这一点:
template <typename... Args>
class MyAlgorithm{
// interact with Args using func1 and func2
};
我现在可以像这样实例化 MyAlgorithm
MyAlgorithm<A, B, C, D, E, F, G>
。这行得通,但是,我觉得对于我的应用程序来说,这可能会导致 MyAlgorithm
的专业化过多。实际上,MyAlgorithm
可能像MyAlgorithm<A, B, B , A, C, D>
一样先被实例化,然后是MyAlgorithm<A, A, C, D>
,然后是MyAlgorithm<C, F D>
,依此类推。
不幸的是,模板是针对 Args
的每个组合实例化的。这会产生问题,例如,在在线设置中。 MyAlgorithm
可能是 运行 批量实时输入数据(MyAlgorithm
的性质是它 运行 批量而不是单个输入)。将解析实时输入数据并调用 MyAlgorithm
的正确特化。在这种情况下,用户将需要在编译代码中创建 MyAlgorithm
所有可能的特化。
MyAlgorithm<A>;
MyAlgorithm<B>;
MyAlgorithm<C>;
MyAlgorithm<A, A>;
MyAlgorithm<A, B>;
MyAlgorithm<A, C>;
MyAlgorithm<B, A>;
...
我有一个想法可能会有所帮助,但我没有完全正确。而不是 MyAlgorithm
采用模板参数,它将处理专门用于 A, B, Cs
.
的模板 Proxy
class
// no template
class MyAlgorithm{
// interact with Proxy using func1proxy and func2proxy
std::vector<Proxy> Args;
};
template<typename T>
class Proxy{
// define func1proxy and func2proxy using Arg's func1 and func2
std::unique_ptr<T> Arg; // only member
};
当然这是行不通的,因为每个 Proxy
专业化都是不同的 class 所以 MyAlgorithm
仍然需要是一个模板 class (并且 std::vector<Proxy> Args
不存在)。
我想做的事情有设计模式吗?是否有一种设计模式可以减少 class 实例化的数量?
一些注意事项:
MyAlgorithm
对所有模板参数一视同仁。该算法在每个模板参数上递归调用 func1
和 func2
。
class MyAlgorithm{
template<typname T, typename... Args>
void CallFunc1s(T first, Args... rest){
T.func1();
SomeFunction(rest);
}
};
类型擦除 func1/func2 调用的类型 T。
struct proxy_ref{
void* pdata=0;
void(*pfunc1)(void*)=0;
void(*pfunc2)(void*)=0;
template<class T>
proxy_ref(T&& t):
pdata((void*)std::addressof(t)),
pfunc1([](void*pvoid){
((T*)pvoid)->func1();
}),
pfunc2([](void*pvoid){
((T*)pvoid)->func2();
})
{}
void func1(){ pfunc1(pvoid); }
void func2(){ pfunc2(pvoid); }
};
现在获取 proxy_ref
的矢量,并在其上调用 func1
和 func2
。
您的特定问题可能涉及更复杂的签名,甚至是值类型而不是引用类型。
像你这样的问题类型擦除无法解决,但尝试这是第一步。
我正在创建一种算法,可以同时处理许多不同的用户定义类型。假定这些类型中的每一个都具有 func1
和 func2
,它们将成为 MyAlgorithm
的接口。我可以使用可变模板来做到这一点:
template <typename... Args>
class MyAlgorithm{
// interact with Args using func1 and func2
};
我现在可以像这样实例化 MyAlgorithm
MyAlgorithm<A, B, C, D, E, F, G>
。这行得通,但是,我觉得对于我的应用程序来说,这可能会导致 MyAlgorithm
的专业化过多。实际上,MyAlgorithm
可能像MyAlgorithm<A, B, B , A, C, D>
一样先被实例化,然后是MyAlgorithm<A, A, C, D>
,然后是MyAlgorithm<C, F D>
,依此类推。
不幸的是,模板是针对 Args
的每个组合实例化的。这会产生问题,例如,在在线设置中。 MyAlgorithm
可能是 运行 批量实时输入数据(MyAlgorithm
的性质是它 运行 批量而不是单个输入)。将解析实时输入数据并调用 MyAlgorithm
的正确特化。在这种情况下,用户将需要在编译代码中创建 MyAlgorithm
所有可能的特化。
MyAlgorithm<A>;
MyAlgorithm<B>;
MyAlgorithm<C>;
MyAlgorithm<A, A>;
MyAlgorithm<A, B>;
MyAlgorithm<A, C>;
MyAlgorithm<B, A>;
...
我有一个想法可能会有所帮助,但我没有完全正确。而不是 MyAlgorithm
采用模板参数,它将处理专门用于 A, B, Cs
.
Proxy
class
// no template
class MyAlgorithm{
// interact with Proxy using func1proxy and func2proxy
std::vector<Proxy> Args;
};
template<typename T>
class Proxy{
// define func1proxy and func2proxy using Arg's func1 and func2
std::unique_ptr<T> Arg; // only member
};
当然这是行不通的,因为每个 Proxy
专业化都是不同的 class 所以 MyAlgorithm
仍然需要是一个模板 class (并且 std::vector<Proxy> Args
不存在)。
我想做的事情有设计模式吗?是否有一种设计模式可以减少 class 实例化的数量?
一些注意事项:
MyAlgorithm
对所有模板参数一视同仁。该算法在每个模板参数上递归调用 func1
和 func2
。
class MyAlgorithm{
template<typname T, typename... Args>
void CallFunc1s(T first, Args... rest){
T.func1();
SomeFunction(rest);
}
};
类型擦除 func1/func2 调用的类型 T。
struct proxy_ref{
void* pdata=0;
void(*pfunc1)(void*)=0;
void(*pfunc2)(void*)=0;
template<class T>
proxy_ref(T&& t):
pdata((void*)std::addressof(t)),
pfunc1([](void*pvoid){
((T*)pvoid)->func1();
}),
pfunc2([](void*pvoid){
((T*)pvoid)->func2();
})
{}
void func1(){ pfunc1(pvoid); }
void func2(){ pfunc2(pvoid); }
};
现在获取 proxy_ref
的矢量,并在其上调用 func1
和 func2
。
您的特定问题可能涉及更复杂的签名,甚至是值类型而不是引用类型。
像你这样的问题类型擦除无法解决,但尝试这是第一步。