捕获函数参数中的一致性
Capture constexpr-ness in function arguments
由于各种原因,我正在寻找一种方法来捕获传递给函数的参数的constexness。这有点难以解释,所以我认为代码最好地展示了我想要实现的
#include <vector> // For std::size_t
#include <cstdio>
namespace
{
template<std::size_t N, typename ...TArgs>
constexpr int cstrlen (char const (&s) [N], std::size_t i = 0) noexcept
{
return i < N && s[i] != 0
? 1 + cstrlen (s, i + 1)
: 0
;
}
template<std::size_t N, typename ...TArgs>
inline void silly_printf (char const (&format) [N], TArgs && ...args) noexcept
{
static_assert (cstrlen (format) > 0, "format must not be empty string");
printf (format, std::forward<TArgs> (args)...);
}
}
#define SILLY_PRINTF(format, ...)
static_assert (cstrlen (format) > 0, "format must not be empty string");
printf (format, ##__VA_ARGS__);
int main()
{
// This works but relies on macros
SILLY_PRINTF ("Hello: %d", 1);
// This doesn't work
silly_printf ("Hello: %d", 1);
return 0;
}
我不能让silly_printf
工作,因为我想要它。编译器抱怨表达式的计算结果不是常量。我们知道当用字符串字面量调用silly_print
时,它是constexpr,但是constexpr会丢失(顺便说一下,我在这里使用VS2015)。
我想也许我可以在参数中添加constexpr(很像const),但没有成功。
我可以使用宏来解决这个问题(由SILLY_PRINTF
宏演示),但感觉像一个失败。
欢迎有任何想法
p。我真正想要实现的是稍微不那么愚蠢
有一个GNU扩展(由g++和clang支持)允许用户定义如下形式的文字:
template<typename CharT, CharT... Chars>
constexpr void operator"" _something() { }
有了这个,可以构建一个不需要宏的constexpr-string类型,可以这样使用:
constexpr auto str = "testing length"_string;
static_assert(str.strlen() == 7, "!");
通过将字符串的所有属性编码到类型中,然后可以在任何地方对其进行static_assert,无论是否为constexpr。例如,在您的sily_printf:
中template<typename CharT, CharT... Chars, typename... Args>
void silly_printf(const constexpr_string<CharT, Chars...>& format_string, Args&&... args) {
static_assert(format_string.strlen() > 0, "format string must not be empty");
printf(format_string.c_str(), args...);
}
并像这样使用:
silly_printf("testing %d %s %x embedded null"_string, 1, "2", nullptr);
您也可以使用另一个operator"" _silly_printf()
返回一个函数对象来获得类似"format string"_silly_printf(args...)
的语法。
在Coliru上观看
不需要使用char数组引用作为参数。这里是我使用的一个,但你需要有c++14宽松的constexpr规则:
using size_t=decltype(sizeof(int));
namespace util
{
template<typename char_t>
constexpr size_t str_size(const char_t*)noexcept;
}
template
<typename char_t>
constexpr auto
util::
str_size
(const char_t* const a_str)noexcept->size_t
{
const char_t* a_char=a_str;
while(*a_char!=char_t(0))
{
++a_char;
}
return size_t(a_char-a_str);
}
static_assert(util::str_size("hello")==size_t(5),"");
如果你不能使用c++14,递归版本也可以。您仍然只是使用char指针作为参数,而不是使用char数组引用。
相关文章:
- 如何反转整数参数包
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 如何使用默认参数等选择模板专业化
- 模板参数替换失败,并且未完成隐式转换
- 具有默认模板参数的多态类的模板推导失败
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 函数调用中参数的顺序重要吗
- 部分定义/别名模板模板参数
- 模板-模板参数推导:三个不同的编译器三种不同的行为
- 使用不带参数的函数访问结构元素
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 如何在OMNET++中指定与命令行参数组合的输出文件名
- 如何使用Luacneneneba API正确读取字符串和表参数
- 在派生函数中指定void*参数
- 视图中的参数推导失败:take_while
- 与具有字符串输出参数的 WinAPI 函数的一致性是多少
- API上函数参数的一致性更改
- 捕获函数参数中的一致性
- 是否可以参数化模板化成员函数的一致性