我想生成printf
版本,该版本会自动将其std::string
参数转换为c_str()
个值。 (我发现printf
语法比C ++流更清晰,更简单。
我想用简单的东西。简短而简单是唯一的设计目标。 Boost有这样的东西,但它太复杂了。我根本不关心效率或完全避免复制。
下面是一个几乎与一个参数一起使用的简单示例。代码有两个问题:
(1)如何将其扩展为任意数量(或至少3个)参数?我知道我可以使用可变参数模板,但我不明白如何在这里使用它们。
(2)当格式参数clang
与要打印的实际对象之间存在类型不匹配时,如何保持编译器警告(-Wall
下const char*
)?
编辑:第(2)部分已基本解决。我在__attribute__((format printf,1,2))
之前添加myprint()
。这样做了类型检查,但要求myprint
是可变的。
示例代码:
#include <stdio.h>
#include <string>
using std::string;
template <typename T>
void myprint(const char* format, T arg){
printf(format, arg);
}
template <>
void myprint(const char* format, string arg){
printf(format,(arg+" STRING ").c_str());
}
int main(){
string x("foo");
myprint ("The value of 1 is: %s\n", "simple"); //works
myprint ("The value of 2 is: %s\n", x); // works
myprint ("The value of 2 is: %d\n", x); // fails - no warning!
printf ("The value of 2 is: %d\n", x.c_str()); // works - warning
return 0;
}
答案 0 :(得分:0)
这里有一个想法:
namespace io {
template <class X>
using is_string = typename std::enable_if<std::is_same<X, std::string>::value>::type;
template <class X>
using is_not_string = typename std::enable_if<!std::is_same<X, std::string>::value>::type;
template <class T, class = is_not_string<T>>
constexpr T forward_or_transform(T t) {
return std::forward<T>(t);
}
template <class T, class = is_string<T>>
constexpr const char* forward_or_transform(T t) {
return t.c_str();
}
template <class ...Ti>
int printf(const std::string& format, Ti...t) {
return std::printf(format.c_str(), forward_or_transform(t)...);
}
}
auto s = std::string("const std::string&");
io::printf("[%s]-[%s]-[%s]-[%d]\n", std::string("std::string&&"), "const char *", s, 42);
打印:[std::string&&]-[const char *]-[const std::string&]-[42]