Currently I have the following code:
static void markPoolsFree(const TNetgroupPools &group_info, TObjectID netiface) {
for (size_t i = 0; i<group_info.public_pools.length();i ++ ) {
SDK::revokeIPPoolFromNetworkInterface(group_info.public_pools[i],netiface);
}
for (size_t i =0 ; i<group_info.private_pool.length(); i++) {
SDK::revokeIPPoolFromNetworkInterface(group_info.private_pool[i].pool_id,
netiface);
}
}
which has basically the same logic, but differents in types group_info.public_pools[i]
and group_info.private_pool[i]
, that's why in second loop we have to add .pool_id
member call. These types are different and don't have any relationships.
I want to rewrite this code to make it more general, for example something like this (sketch):
// template function
template <typename Container, typename PredArgs>
static void revokeIPPool(const Container &pool, TObjectID netiface,
bool (*pred)(PredArgs pool_id, PredArgs netiface_id))
{
for (size_t i = 0; i < pool.length(); ++i) {
if (pred(pool[i], netiface)) {
SDK::revokeIPPoolFromNetworkInterface(pool[i], netiface);
}
}
}
// calling code
static void markPoolsFree(const TNetgroupPools &group_info, TObjectID netiface) {
revokeIPPool(group_info.public_pools, netiface, SDK::isPredicateTrue);
revokeIPPool(group_info.private_pool, netiface, SDK::isPredicateTrue);
}
But the problem is in different types for public_pools
and private_pool
.
Question: Could you give all ways how is possible to generalize this code with examples? I need C++03 code, but C++11/C++14 is acceptable.
My thoughts:
SDK::revokeIPPoolFromNetworkInterface
make wrapperIPPool
with overloads for both types and call SDK::revokeIPPoolFromNetworkInterface
internally.revokeIPPool
for both types (but it's code duplication, no improvement against original code)revokeIPPool
(is this possible?)revokeIPPool
revokeIPPool
in class and make partial class template specialization.Questions:
In C++03 I'd use template specialization on a traits class. (The main reason for going through a traits class, rather than using direct function specialisation, or overload is that you can perform partial template specialisation for classes, but not functions - and while its not needed here, it may be something that is useful later )
static void markPoolsFree(const TNetgroupPools &group_info, TObjectID netiface) {
markPoolsFreeImpl(group_info.public_pools, netiface);
markPoolsFreeImpl(group_info.private_pools, netiface);
}
template<typename T>
static void markPoolsFreeImpl(POOLS pools, TObjectID netiface) {
for (size_t i = 0; i<pools.length();i ++ ) {
PoolId poolid = PoolListTrait<POOLS>::get(pools,i);
SDK::revokeIPPoolFromNetworkInterface(poolid,netiface);
}
}
template<typename T> class PoolListTrait {};
template<> class PoolListTrait<PublicPoolList> {
static PoolId get(PublicPoolList pools, int i) { return pools[i]; }
}
template<> class PoolListTrait<PrivatePoolList> {
static PoolId get(PrivatePoolList pools, int i) { return pools[i].pool_id; }
}
Dunno if generic lambdas (C++14) are an acceptable solution for you:
auto revoke_pool = [](auto &pool, TObjectID netiface, auto extract_item)
{
for(std::size_t i = 0; i < pool.length(); ++i)
SDK::revokeIPPoolFromNetworkInterface(extract_item(pool, i), netiface);
};
Then you only hace to define a lambda to access the pool item.
revoke_pool(group_info.public_pools, netiface, [](auto &pool, std::size_t idx) { return pool[idx]; });
revoke_pool(group_info.private_pool, netiface, [](auto &pool, std::size_t idx) { return pool[idx].pool_id; });
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With