如何删除 typename 中每个元素的 const ref 修饰符... T
How to remove const ref modifiers for each element in typename... T
我刚开始用可变参数版本替换我的一些旧模板,以避免因参数数量可变的重载而导致代码重复(或丑陋的宏)。
我 运行 遇到但尚未解决的一个问题是:如何从属于 'mixed typename...' 的任何类型中删除 const& ?
这是我的例子:
#include <tuple>
// old version to be replaced
namespace old_version
{
template<typename T> struct struct_const_deref { typedef T Type; };
template<typename T> struct struct_const_deref < const T& > { typedef T Type; };
template < typename F, typename T1 >
void exec(F* pObj, void(F::*pFct)(T1))
{
typename struct_const_deref<T1>::Type t1;
// some code that fills t1
(pObj->*pFct)(t1);
}
template < typename F, typename T1 , typename T2 >
void exec(F* pObj, void(F::*pFct)(T1, T2))
{
typename struct_const_deref<T1>::Type t1;
typename struct_const_deref<T2>::Type t2;
// some code that fills t1, t2
(pObj->*pFct)(t1, t2);
}
}
// new variadic version
namespace variadic
{
template< typename... Args > struct struct_const_deref_tuple { typedef std::tuple< Args... > Tuple; };
template< typename... Args > struct struct_const_deref_tuple < const Args&... > { typedef std::tuple< Args... > Tuple; };
template < typename F, typename... Args >
void exec(F* pObj, void(F::*pFct)(Args... args))
{
typename struct_const_deref_tuple< Args... >::Tuple tN;
// some code that fills tN
// some helper template that 'extracts' the tuple and calls (pObj->*pFct)(ExtractedArgs...)
}
}
struct Test
{
void foo(int i) {}
void bar(const float& f, const int& i) {}
void buu(const float& f, int i) {}
};
int main(int argc, char* argv[])
{
Test t;
old_version::exec(&t, &Test::foo); // ok
old_version::exec(&t, &Test::bar); // ok
old_version::exec(&t, &Test::buu); // ok
variadic::exec(&t, &Test::foo); // ok
variadic::exec(&t, &Test::bar); // ok
variadic::exec(&t, &Test::buu); // fails (the struct_const_deref_tuple does not 'catch' my case; 'tN' will be std::tuple<const float&, int>
return 0;
}
由于旧解决方案需要为每个参数数量分配一个版本,因此我想将其替换为可变参数解决方案。
不幸的是可变版本在
上失败
Test::buu
因为 tN 变为
std::tuple<const float&, int>
但显然需要
std::tuple<float, int>
为了我工作。
欢迎提出任何想法:)
本质问题是pack expansion。此外,为简单起见,您可以使用 type_traits 中的 std::decay(c++11) 或 std::decay_t (c++14)。以下代码应使用 c++14 编译。
#include <tuple>
#include <type_traits>
// new variadic version
namespace variadic
{
template < typename F, typename... Args >
void exec(F* pObj, void(F::*pFct)(Args... args))
{
std::tuple<std::decay_t<Args>...> tN;
// some code that fills tN
// some helper template that 'extracts' the tuple and calls (pObj->*pFct)(ExtractedArgs...)
}
}
struct Test
{
void foo(int i) {}
void bar(const float& f, const int& i) {}
void buu(const float& f, int i) {}
};
int main(int argc, char* argv[])
{
Test t;
variadic::exec(&t, &Test::foo); // ok
variadic::exec(&t, &Test::bar); // ok
variadic::exec(&t, &Test::buu); // ok
return 0;
}
请看这个
#include <type_traits>
template<typename T>
struct RemoveConst;
template<typename T>
struct RemoveConst{
using type = typename std::remove_const<T>::type;
};
template<typename T>
struct RemoveConst<const T>{
using type = typename RemoveConst<T>::type;
};
template<typename T>
struct RemoveConst<const T*>{
using type = typename RemoveConst<T>::type*;
};
template<typename T>
struct RemoveConst<T* const>{
using type = typename RemoveConst<T>::type*;
};
template<template <typename...> class T, typename... Args>
struct RemoveConst<T<Args...>>{
using type = T<typename RemoveConst<Args>::type...>;
};
这些 classes 递归地从给定类型中删除 const
以及模板的所有模板参数 class。
我刚开始用可变参数版本替换我的一些旧模板,以避免因参数数量可变的重载而导致代码重复(或丑陋的宏)。
我 运行 遇到但尚未解决的一个问题是:如何从属于 'mixed typename...' 的任何类型中删除 const& ?
这是我的例子:
#include <tuple>
// old version to be replaced
namespace old_version
{
template<typename T> struct struct_const_deref { typedef T Type; };
template<typename T> struct struct_const_deref < const T& > { typedef T Type; };
template < typename F, typename T1 >
void exec(F* pObj, void(F::*pFct)(T1))
{
typename struct_const_deref<T1>::Type t1;
// some code that fills t1
(pObj->*pFct)(t1);
}
template < typename F, typename T1 , typename T2 >
void exec(F* pObj, void(F::*pFct)(T1, T2))
{
typename struct_const_deref<T1>::Type t1;
typename struct_const_deref<T2>::Type t2;
// some code that fills t1, t2
(pObj->*pFct)(t1, t2);
}
}
// new variadic version
namespace variadic
{
template< typename... Args > struct struct_const_deref_tuple { typedef std::tuple< Args... > Tuple; };
template< typename... Args > struct struct_const_deref_tuple < const Args&... > { typedef std::tuple< Args... > Tuple; };
template < typename F, typename... Args >
void exec(F* pObj, void(F::*pFct)(Args... args))
{
typename struct_const_deref_tuple< Args... >::Tuple tN;
// some code that fills tN
// some helper template that 'extracts' the tuple and calls (pObj->*pFct)(ExtractedArgs...)
}
}
struct Test
{
void foo(int i) {}
void bar(const float& f, const int& i) {}
void buu(const float& f, int i) {}
};
int main(int argc, char* argv[])
{
Test t;
old_version::exec(&t, &Test::foo); // ok
old_version::exec(&t, &Test::bar); // ok
old_version::exec(&t, &Test::buu); // ok
variadic::exec(&t, &Test::foo); // ok
variadic::exec(&t, &Test::bar); // ok
variadic::exec(&t, &Test::buu); // fails (the struct_const_deref_tuple does not 'catch' my case; 'tN' will be std::tuple<const float&, int>
return 0;
}
由于旧解决方案需要为每个参数数量分配一个版本,因此我想将其替换为可变参数解决方案。
不幸的是可变版本在
上失败Test::buu
因为 tN 变为
std::tuple<const float&, int>
但显然需要
std::tuple<float, int>
为了我工作。
欢迎提出任何想法:)
本质问题是pack expansion。此外,为简单起见,您可以使用 type_traits 中的 std::decay(c++11) 或 std::decay_t (c++14)。以下代码应使用 c++14 编译。
#include <tuple>
#include <type_traits>
// new variadic version
namespace variadic
{
template < typename F, typename... Args >
void exec(F* pObj, void(F::*pFct)(Args... args))
{
std::tuple<std::decay_t<Args>...> tN;
// some code that fills tN
// some helper template that 'extracts' the tuple and calls (pObj->*pFct)(ExtractedArgs...)
}
}
struct Test
{
void foo(int i) {}
void bar(const float& f, const int& i) {}
void buu(const float& f, int i) {}
};
int main(int argc, char* argv[])
{
Test t;
variadic::exec(&t, &Test::foo); // ok
variadic::exec(&t, &Test::bar); // ok
variadic::exec(&t, &Test::buu); // ok
return 0;
}
请看这个
#include <type_traits>
template<typename T>
struct RemoveConst;
template<typename T>
struct RemoveConst{
using type = typename std::remove_const<T>::type;
};
template<typename T>
struct RemoveConst<const T>{
using type = typename RemoveConst<T>::type;
};
template<typename T>
struct RemoveConst<const T*>{
using type = typename RemoveConst<T>::type*;
};
template<typename T>
struct RemoveConst<T* const>{
using type = typename RemoveConst<T>::type*;
};
template<template <typename...> class T, typename... Args>
struct RemoveConst<T<Args...>>{
using type = T<typename RemoveConst<Args>::type...>;
};
这些 classes 递归地从给定类型中删除 const
以及模板的所有模板参数 class。