Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 捕获函数参数中的constexpr_C++_C++14_Constexpr - Fatal编程技术网

C++ 捕获函数参数中的constexpr

C++ 捕获函数参数中的constexpr,c++,c++14,constexpr,C++,C++14,Constexpr,出于各种原因,我正在寻找一种方法来捕获传递给函数的参数的常量。解释起来有点棘手,所以我认为代码最能说明我想要实现的目标 #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

出于各种原因,我正在寻找一种方法来捕获传递给函数的参数的常量。解释起来有点棘手,所以我认为代码最能说明我想要实现的目标

#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;
}
#包括//标准::尺寸#
#包括
名称空间
{
模板
constexpr int cstrlen(char const(&s)[N],std::size\u t i=0)无例外
{
返回i0,“格式不能为空字符串”);
printf(格式,标准::转发(args)…);
}
}
#定义打印格式(格式,…)\
静态_断言(cstrlen(format)>0,“格式不能为空字符串”)\
printf(格式,###uu VA_uargs_uu);
int main()
{
//这是可行的,但依赖于宏
愚蠢的PRINTF(“你好:%d”,1);
//这不管用
愚蠢的printf(“你好:%d”,1);
返回0;
}
我不能让愚蠢的printf像我希望的那样工作。编译器抱怨表达式的计算结果不是常量。我们知道,当使用字符串文本调用
silly\u print
时,它是constexpr,但是constexpr ness丢失了(顺便说一下,我在这里使用的是VS2015)

我在想也许我可以将constexpr添加到参数中(很像const),但没有成功

我可以使用宏来解决这个问题(通过
SILLY\u PRINTF
macro演示),但这感觉像是失败了

欢迎提出任何意见


顺便说一句,我真正想要实现的是稍微少一点愚蠢

您不需要使用字符数组引用作为参数。这里是我使用的一个,但您需要有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),"");
使用size_t=decltype(sizeof(int));
命名空间util
{
模板
constexpr size\u t str\u size(const char\u t*)无例外;
}
模板
康斯特普汽车公司
util::
str_尺寸
(常量字符*常量字符)无异常->大小
{
const char_t*a_char=a_str;
while(*a_char!=char_t(0))
{
++a_char;
}
返回大小(a_char-a_str);
}
静态断言(util::str_size(“hello”)==size_t(5),“”);
如果你不能使用c++14,递归版本也可以。您仍然使用char指针作为参数,而不是char数组引用。

有一个GNU扩展(由g++和clang支持),允许用户定义以下形式的文本:

template<typename CharT, CharT... Chars>
constexpr void operator"" _something() { }
通过将字符串的所有属性编码到类型中,您可以在任何位置对其进行静态断言,无论是否为constexpr。 例如,在您的傻瓜打印F中:

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...);
}
您还可以使用另一个
操作符“”\u silly\u printf()
返回函数对象,以获得类似
“格式字符串”\u silly\u printf(args…)
的语法


cstrlen(格式)
替换为
N
?一种方法是使用
模板结构字符列表{}。但是从我知道的文本字符串构建它的方法也使用宏(因此它的结果类似于
silly\u printf(to\u CHAR\u LIST(“hello:%d”),1)
)。@KerrekSB:这不处理
“\0Hidden text”
。宏
silly\u printf(“hello:%d”,1)也不起作用。我使用了你的代码并注释掉了行
silly\u printf(“Hello:%d”,1)在main中,并在
pully\u PRINTF
宏上获取错误。原因是,尽管有
constepr
说明符,
ctrlen
不返回常量表达式,因为
i
参数不是常量表达式。@SergeBallesta当我使用clang(3.6.0)和gcc(4.9.2)以及选项--std=c++14运行时,它们能够编译宏版本。我对标准不太了解,无法说出它应该做什么。也许编译器太宽松了?嗨,我会评估一下。如果我能让它发挥作用,放松的规则似乎是一个显著的进步。宽松的规则是标准化的还是某些特定的编译器支持?哪些编译器支持宽松的规则。我想这就是你所说的:。这将是一个巨大的帮助,尤其是在解析字符串时减少模板编译深度。叮当声似乎在那里,但还没有GCC(版本5),但我想知道它是否仍然能让我摆脱宏。表达式仍然需要是constexpr。我需要评估一下。嗨。我假设这依赖于用户定义的文本。这是一个有趣的想法,我可以这样做:
“我的格式字符串:%s”\u format
,它返回一个
格式化程序\u字符串(或类似的东西),在编译时进行解析和检查。我将进行调查。@FuleSnabel不幸的是,VS2015中既不支持relaxed constexpr,也不支持这些字符串用户定义的文本。relaxed constexpr缺失,但至少有一些对UDT的支持。这似乎适合我:
constexpr std::size_t operator”“_format(const char*deg,std::size_t n){return n;}
这似乎是避免在C++14中使用宏的最佳方法。
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\0null"_string, 1, "2", nullptr);