如何在积分类型的模板函数中选择snprinf掩码
How to choose snprinf mask in template function for integral type?
我有一个模板函数,它接受一个整型参数,并将其复制到具有std::snprintf
:的堆栈上的字符数组中
static const size_t size = 256;
char buffer[size];
template <class T, std::enable_if<std::is_integral<T>::value, T>::type>
bool to_array(T integer) {
auto ret = std::snprint(buffer, size, "%lld", integer);
return ret > 0;
}
问题是,例如,如果此函数与int
类型一起使用,编译器会打印警告,即"%lld"
掩码需要long long int
类型。
为了修复它,我使用了boost::fusion::map
:
using bf = boost::fusion;
using integral_masks = bf::map<
bf::pair<char, const char*>,
bf::pair<short, const char*>,
....
bf::pair<unsigned long long, const char*>
>;
integral_masks masks(
bf::make_pair<char>("%c"),
bf::make_pair<int>("%d"),
....
bf::make_pair<unsigned long>("%lu")
bf::make_pair<unsigned long long>("%llu")
);
auto ret = std::snprint(buffer, size, bf::at_key<T>(masks), integer);
这是可行的,但它看起来有点重,并且boost::fusion
标头显著增加了编译时间。也许有更好更简单的方法可以做到这一点?
由于您"试图避免分配",并且您无论如何都在使用boost:使用boost Iostreams自定义设备
PS为了避免不明显,使用流可以获得所有好处:
- 如果需要printf样式或位置参数格式字符串,请与Boost Format组合使用
- 与Boost Locale结合用于本地化消息(
gettext
)和格式设置(序数、日期、数字…)
在Coliru上直播
#include <array>
#include <boost/iostreams/device/array.hpp>
#include <boost/iostreams/stream.hpp>
#include <iostream>
namespace io = boost::iostreams;
int main()
{
std::array<char, 128> buf;
auto b = buf.begin(), e = buf.end();
io::array_sink as(b, e);
io::stream<io::array_sink> os(as);
os << '1' << uint16_t(42) << uint32_t(42) << std::showbase << std::hex << int64_t(-1) << "n"
<< std::boolalpha << false << "n"
<< std::numeric_limits<double>::infinity();
std::cout << "result '" << std::string(b, os.tellp()) << "'n";
}
这将在buf
已填充之后停止写入输出。
实际上,您可能只想要back_inserter
。通过这种方式,你可以两全其美:控制分配,同时不受任意限制。
另请参阅std::string::reserve
以了解进一步的优化。您可以随心所欲地重用该字符串,而不会产生更多的分配。
在Coliru上直播
#include <array>
#include <boost/iostreams/device/back_inserter.hpp>
#include <boost/iostreams/stream.hpp>
#include <iostream>
namespace io = boost::iostreams;
int main()
{
std::string buf;
io::stream<io::back_insert_device<std::string> > os(io::back_inserter(buf));
os << '1' << uint16_t(42) << uint32_t(42) << std::showbase << std::hex << int64_t(-1) << "n"
<< std::boolalpha << false << "n"
<< std::numeric_limits<double>::infinity();
os.flush();
std::cout << "result '" << buf << "'n";
}
以上两种使用都在仅标头模式下使用Boost Iostreams(在运行时不依赖于Boost(共享)库)。
您可以使用constexpr
函数:
constexpr const char* format_of(char) { return "%c"; }
constexpr const char* format_of(int) { return "%d"; }
constexpr const char* format_of(unsigned long) { return "%lu"; }
constexpr const char* format_of(unsigned long long) { return "%llu"; }
实例
相关文章:
- 选择要调用的构造函数
- 无法获取菜单选择以运行函数.C++
- 表达式 SFINAE:如何根据类型是否包含具有一个或多个参数的函数来选择模板版本
- LLVM 选择找不到函数传递
- C++ 带有默认参数的结构,可选择在构造函数中更改
- 如何在"push_*()"和"emplace_*()"函数之间进行选择?
- 如何在字符函数中选择某些字符?
- OpenCL 内置函数选择
- 编译时构造函数选择
- 内联函数选择条件
- c - 函数选择显示读取后stdin中有数据
- Clang 和 GCC 在使用大括号表示法和initializer_list时在构造函数选择上存在分歧
- 最小化函数选择和函数调用开销
- 当参数是引用时,可变模板构造函数选择失败
- 在运行时为调用函数选择对象,不包含基类和模板
- 为什么const临时函数选择调用非const成员函数而不是const成员函数?
- 如何消除构造函数选择的强制转换
- 是否有可能编写一个抽象类,其中构造函数选择适当的子类在c++中实例化
- c++模板函数选择
- vector insert中重载模板函数选择(模式匹配)是如何工作的