Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/142.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作为std::数组大小_C++_Visual Studio 2019 - Fatal编程技术网

C++ 使用constexpr作为std::数组大小

C++ 使用constexpr作为std::数组大小,c++,visual-studio-2019,C++,Visual Studio 2019,我有以下使用constepr作为数组大小的代码 #include <array> template <size_t size> constexpr size_t GetSize(const char(&format)[size]) { // Iterate over format array and compute a value. size_t count = 0; for (size_t i = 0; i < size; ++i

我有以下使用
constepr
作为数组大小的代码

#include <array>

template <size_t size>
constexpr size_t
GetSize(const char(&format)[size])
{
    // Iterate over format array and compute a value.
    size_t count = 0;
    for (size_t i = 0; i < size; ++i)
    {
        if (format[i] == '%')
        {
            ++count;
        }
    }

    return count;
}

template <size_t size>
constexpr auto
GetArray(const char(&format)[size])
{
    constexpr size_t arraySize = GetSize(format);
    return std::array<char, arraySize>();
}

int main(int argc, char** argv)
{
    static_assert(GetArray("hello").size() == 12, "failed");
}
#包括
模板
constexpr大小
GetSize(常量字符和格式)[size])
{
//迭代格式化数组并计算一个值。
大小\u t计数=0;
对于(大小i=0;i
但是,它无法在VS2019下编译,出现以下错误

error C2131:  expression did not evaluate to a constant
message :  failure was caused by a read of a variable outside its lifetime
message :  see usage of 'format'
message :  see reference to function template instantiation 'auto GetArray<6>(const char (&)[6])' being compiled
错误C2131:表达式的计算结果不是常量
消息:失败是由于在变量的生存期之外读取变量造成的
消息:请参阅“格式”的用法
消息:请参阅正在编译的函数模板实例化“auto GetArray(const char(&)[6])”的参考

这是一个编译器错误吗?如果是,是否有解决方法?

我不知道您是否绝对需要将
GetSize()
函数用于其他用途,但在GetArray中,您已经可以访问数组的长度,因此您可以执行以下操作:

#include <array>

template <std::size_t N>
constexpr auto
GetArray(const char(&format)[N])
{
    return std::array<char, N*2>{};
}

int main(int argc, char** argv)
{
    static_assert(GetArray("hello").size() == 12, "failed");
}
#包括
模板
康斯特普汽车公司
GetArray(常量字符和格式)[N])
{
返回std::数组{};
}
int main(int argc,字符**argv)
{
静态_断言(GetArray(“hello”).size()==12,“失败”);
}

constexpr函数的问题是,您可以使用constexpr参数和非constexpr参数调用:

int constexpr f(int n)
{
    return ++n;
}

int constexpr n0 = 7;
int n1; std::cin >> n1;
f(n0); // result IS constexpr
f(n1); // result is NOT constexpr, just an ordinary int
由于此特性,函数参数本身不能是constexpr,或者更准确地说,不能在constexpr上下文中使用。因此,在您的功能中:

constexpr size_t arraySize = getSize(format);
//                                      ^ cannot be used as constexpr, even if
//                                        constexpr has been passed to, so result
//                                        not either (the f(n1) case above)
您可以稍微修改第二个函数:

template <size_t Size>
constexpr auto
getArray()
{
    return std::array<char, Size>();
}
模板
康斯特普汽车公司
getArray()
{
返回std::array();
}
像这样使用它

int main(int argc, char** argv)
{
    static_assert(getArray<getSize("hello")>().size() == 0, "failed");
    return 0;
}
int main(int argc,char**argv)
{
静态_断言(getArray().size()==0,“失败”);
返回0;
}
当然,现在看起来很难看,但您可能隐藏在宏后面:

#define myGetArray(STRING) getArray<getSize(STRING)>()
#定义myGetArray(字符串)getArray()
或者干脆

#define getArray(STRING) std::array<char, getSize(STRING)>()
#定义getArray(STRING)std::array()

这里是一个C++17工作解决方案,使用lambda将char数组包装为constexpr

#include <array>
#include <string>

template <typename Char_Array_Holder>
constexpr size_t GetSize(Char_Array_Holder holder)
{
  // Iterate over format array and compute a value.
  constexpr std::string_view format = holder();

  size_t count = 0;
  for (char c : format)
  {
    if (c == '%')
    {
      ++count;
    }
  }

  return count;
}

template <typename Char_Array_Holder>
constexpr auto GetArray(Char_Array_Holder holder)
{
  constexpr size_t arraySize = GetSize(holder);
  return std::array<char, arraySize>();
}

#define hold(msg) []() { return msg; }

int main(int argc, char** argv)
{
  static_assert(GetArray(hold("hello")).size() == 0, "failed...");
  static_assert(GetArray(hold("h%ello")).size() == 1, "failed...");
  static_assert(GetArray(hold("h%el%%lo")).size() == 3, "failed...");
}

#include您可以阅读以获取更多信息

进行比较:GCC 8.1(linux)毫无怨言地接受。
arraySize
不能是constexpr,因为格式不是constexpr,我猜。ICC和Clang还报告,作为一个错误,我实际上必须迭代格式数组来计算大小。更新了代码。