注意:我在函数的模糊重载中添加了类似但大大简化的问题版本,例如`msg(long)`与候选`msg(int32_t)`和`msg(int64_t)`.该版本具有在单个文件中完整可编译示例的优点.
我有一个C库,其功能类似于
obj_from_int32(int32_t& i);
obj_from_int64(int64_t& i);
obj_from_uint32(uint32_t& i);
obj_from_uint64(uint64_t& i);
Run Code Online (Sandbox Code Playgroud)
在这种情况下,类型int32_t等都是不所述std的-它们是实现定义的,在这种情况下字符数组(在下面的例子中我省略转换-它不会改变的问题是有关映射可积类型到基于积分类型中位数的特定函数).
我有第二个C++接口类,它有类似的构造函数
MyClass(int z);
MyClass(long z);
MyClass(long long z);
MyClass(unsigned int z);
MyClass(unsigned long z);
MyClass(unsigned long long z);
Run Code Online (Sandbox Code Playgroud)
注意,我不能用std::int32_t样式类型替换这个接口- 如果我可以,我不需要问这个问题;)
问题是如何obj_from_根据积分类型中的位数调用正确的函数.
我提出了两个建议的解决方案,因为没有任何杀手级解决方案浮动到列表的顶部,并且有一些解决方案已被打破.
由干杯和赫斯提供.-阿尔夫.从这一点开始的评论是我自己的 - 随意评论和/或编辑.
优点
- 相当简单(至少相比boost::enable_if) - 不依赖于第三方库(只要编译器支持tr1)
*缺点** - 如果需要更多功能(如anotherObj_from_int32等),则需要更多代码
这个解决方案可以在下面找到 - 看看,它很漂亮!
好处
一旦ConvertFromIntegral功能完成后,添加需要转换为有价值的新功能-只需编写一组重载的int32_t,int64_t和未签名的等价物.
仅将模板用于一个地方,它们不会随着技术的重复使用而传播.
缺点
boost::enable_if.这只是在一次出现的事实有所减轻.因为这是我自己的,所以我不能接受它,但是如果你觉得它很整洁就可以投票(很明显有些人根本不认为它很整洁,我认为这就是它的优点!)感谢大家贡献了想法!
该解决方案包括从一个转换功能int,long以及long long以int32_t和int64_t(和用于无符号版本相似).这是用另一个组重载上功能相结合int32_t,int64_t和无符号的等同物.这两个函数可以组合在一起,但是第一个转换函数创建了一个可以重用的便捷实用工具集,然后第二组函数非常简单.
// Utility conversion functions (reuse wherever needed)
template <class InputT>
typename boost::enable_if_c<sizeof(InputT)==sizeof(int32_t) && boost::is_signed<InputT>::value,
int32_t>::type ConvertFromIntegral(InputT z) { return static_cast<int32_t>(z); }
template <class InputT>
typename boost::enable_if_c<sizeof(InputT)==sizeof(int64_t) && boost::is_signed<InputT>::value,
int64_t>::type ConvertFromIntegral(InputT z) { return static_cast<int64_t>(z); }
template <class InputT>
typename boost::enable_if_c<sizeof(InputT)==sizeof(uint32_t) && boost::is_unsigned<InputT>::value,
uint32_t>::type ConvertFromIntegral(InputT z) { return static_cast<uint32_t>(z); }
template <class InputT>
typename boost::enable_if_c<sizeof(InputT)==sizeof(uint64_t) && boost::is_unsigned<InputT>::value,
uint64_t>::type ConvertFromIntegral(InputT z) { return static_cast<uint64_t>(z); }
// Overload set (mock implementation, depends on required return type etc)
void* objFromInt32 (int32_t i) { obj_from_int32(i); }
void* objFromInt64 (int64_t& i) { obj_from_int64(i); }
void* objFromUInt32(uint32_t& i) { obj_from_uint32(i); }
void* objFromUInt64(uint64_t& i) { obj_from_uint64(i); }
// Interface Implementation
MyClass(int z) : _val(objFromInt(ConvertFromIntegral(z))) {}
MyClass(long z): _val(objFromInt(ConvertFromIntegral(z))) {}
MyClass(long long z): _val(objFromInt(ConvertFromIntegral(z))) {}
MyClass(unsigned int z): _val(objFromInt(ConvertFromIntegral(z))) {}
MyClass(unsigned long z): _val(objFromInt(ConvertFromIntegral(z))) {}
MyClass(unsigned long long z): _val(objFromInt(ConvertFromIntegral(z))) {}
Run Code Online (Sandbox Code Playgroud)
一个简化的(单个可编译.cpp!)版本的解决方案是在函数的模糊重载中给出的,例如`msg(long)`与候选`msg(int32_t)`和`msg(int64_t)`
除了重载之外,模式匹配又如何呢?使用boost::enable_if帮助程序模板来选择您正在寻找的操作类型?
像这样的东西:
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <iostream>
template <typename T, typename Dummy=void> struct helper;
// Handle signed integers of size 1 (8 bits)
template <typename T> struct helper<T,
typename boost::enable_if_c<
boost::is_integral<T>::value &&
(sizeof(T)==1) &&
(static_cast<T>(-1) < static_cast<T>(0)) >::type>
{
static void do_stuff(T const& ) {std::cout<<"signed, size 1"<<std::endl;}
};
// Handle unsigned integers of size 1 (8 bits)
template <typename T> struct helper<T,
typename boost::enable_if_c<
boost::is_integral<T>::value &&
(sizeof(T)==1) &&
(static_cast<T>(-1) > static_cast<T>(0)) >::type>
{
static void do_stuff(T const& ) {std::cout<<"unsigned, size 1"<<std::endl;}
};
// Handle signed integers of size 2 (16 bits)
template <typename T> struct helper<T,
typename boost::enable_if_c<
boost::is_integral<T>::value &&
(sizeof(T)==2) &&
(static_cast<T>(-1) < static_cast<T>(0)) >::type>
{
static void do_stuff(T const& ) {std::cout<<"signed, size 2"<<std::endl;}
};
// And so on and so forth....
// Use a function for type erasure:
template <typename T> void do_stuff(T const& value)
{
helper<T>::do_stuff(value);
}
int main()
{
do_stuff(static_cast<unsigned char>(0)); // "unsigned, size 1"
do_stuff(static_cast<signed short>(0)); // "signed, size 2"
}
Run Code Online (Sandbox Code Playgroud)
更完整的列表(并证明它至少适用于 GCC)位于http://ideone.com/pIhdq。
编辑:或者更简单,但覆盖范围可能较少:(使用标准整数类型)
template <typename T> struct helper2;
template <> struct helper2<uint8_t> {static void do_stuff2(uint8_t ) {...}};
template <> struct helper2<int8_t> {static void do_stuff2(int8_t ) {...}};
template <> struct helper2<uint16_t> {static void do_stuff2(uint16_t ) {...}};
template <> struct helper2<int16_t> {static void do_stuff2(int16_t ) {...}};
// etc.
template <typename T> void do_stuff2(T value) {helper2<T>::do_stuff2(value);}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1280 次 |
| 最近记录: |