标签: constexpr

constexpr 中允许未定义的行为——编译器错误?

我的理解是:

  • C++ 中的有符号整数溢出是未定义的行为
  • 常量表达式不允许包含未定义的行为。

看来像下面这样的东西不应该编译,事实上在我的编译器上它不编译。

template<int n> struct S { };

template<int a, int b>
S<a * b> f()
{
  return S<a * b>();
}

int main(int, char **)
{
  f<50000, 49999>();
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

但是,现在我尝试以下方法:

#include <numeric>

template<int n> struct S { };

template<int a, int b>
S<std::lcm(a, b)> g()
{
  return S<std::lcm(a,b)>();
}

int main(int, char **)
{
  g<50000, 49999>();
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

g++、clang 和 MSVC 都会愉快地编译它,尽管事实上

如果 |m|、|n| 或 |m| 的最小公倍数,则行为未定义 和|n| 不能表示为 type 的值 std::common_type_t<M, N> …

c++ undefined-behavior constexpr

6
推荐指数
1
解决办法
257
查看次数

一个 constexpr 函数,用于计算 std::vector 的嵌套深度

有没有办法编写一个 constexpr 函数来返回 std::vector 的嵌套深度?

例子:

get_vector_nested_layer_count<std::vector<std::vector<int>>>() // 2
get_vector_nested_layer_count<std::vector<std::vector<std::vector<float>>>>() // 3
Run Code Online (Sandbox Code Playgroud)

c++ templates constexpr constexpr-function

6
推荐指数
2
解决办法
386
查看次数

为什么成员函数不能要求同一类的 static constexpr 成员为 true?

我尝试让成员函数要求静态 constexpr 布尔成员为 true。这对于 DRY 一个相当复杂的需求非常有帮助。我不知道编译器不允许我这样做的原因。

要求稍微不那么复杂的最小示例:

template <typename T>
struct Foo
{
    static constexpr bool isInt = std::integral<T>;
    void bar() requires (isInt);
    void goo() requires std::integral<T>;
};

template <typename T>
void Foo<T>::bar() requires (Foo<T>::isInt) // error: out-of-line definition of 'bar' does not match any declaration in 'Foo<T>' x86-64 clang 14.0.0 #1
{
    // ...
}

template <typename T>
void Foo<T>::goo() requires std::integral<T> // ok
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)

这是因为isInt是在同一个类中声明的吗?或者我有某种语法错误?

c++ constexpr c++20 requires-clause

6
推荐指数
1
解决办法
135
查看次数

为什么`constexpr向量`不允许在`consteval`函数中分配?

第四次编辑:原始问题标题是:

为什么constexpr说明符不允许非空std::vector

正如 @Barry 指出的,这个标题与C++20 constexpr vector and string not working重复。但我的问题描述有所不同:我constexpr vectorconstevalfunction而不是正常的运行时 function 或constexprfunction中分配。

据我所知,在编译时计算期间,只允许瞬时分配,正如 @Barry 在链接问题中回答的那样。

我感到困惑的是:对于consteval功能:

  1. 它的任何局部变量将在返回后被释放
  2. 它只在编译时返回,因为它只会在编译时被调用
  3. soconstexpr vector作为局部变量,将在编译时释放
  4. 那么为什么不允许呢?

我在下面的其他编辑回答了这个困惑。

-----------------以下是原问题描述----------

为什么下面的代码不能编译:

consteval int foo() {
  constexpr std::vector<int> vec{1};
  return vec[0];
}
Run Code Online (Sandbox Code Playgroud)

据我所知,只要分配和释放都发生在编译时,就可以在编译时使用 和std::vectorstd::string如果我删除constexpr说明符,该代码将编译。

但是添加constexpr仍然不违反这个规则,对吗?为什么不允许?

使用 gcc 13 编译时出现此错误,但我不明白:

/opt/compiler-explorer/gcc-13.1.0/include/c++/13.1.0/bits/allocator.h:195:52: error:
'std::vector<int>(std::initializer_list<int>{((const int*)(& …
Run Code Online (Sandbox Code Playgroud)

c++ constexpr c++20

6
推荐指数
0
解决办法
249
查看次数

numeric_limits min/max constexpr?

是否C++ 11标准指定的numeric_limits<T>::minmax必须是能够在模板或使用常数表达式static_assert

更一般地说,如何根据标准找到常量表达式的函数列表?

c++ standards-compliance constexpr c++11

5
推荐指数
1
解决办法
1907
查看次数

如何使用外部链接在命名空间范围内定义常量double?

我正在尝试使用外部链接创建名称空间范围常量

// in some include file:

namespace foo 
{
    constexpr double bar() { return 1.23456; } // internal linkage
    constexpr double baz = 1.23456;            // internal linkage
    const double bing = 1.23456;               // internal linkage
}
Run Code Online (Sandbox Code Playgroud)

这甚至可能吗?

c++ constexpr c++11

5
推荐指数
1
解决办法
955
查看次数

如何使用0值的对象初始化指针

在"C++ Primer,5th ed",第2.4.4节中,整个部分解释了"constexpr".然后在书中给出了如下练习:

练习2.32:以下代码是否合法?如果没有,你怎么能让它合法?

int null = 0, *p = null;
Run Code Online (Sandbox Code Playgroud)

我知道修复它的一种快速方法是将其更改为*p = nullptr或NULL,或使用reinterpret_cast.但我认为这本书的目的是使用与constexpr相关的东西.所以我的问题是,如何正确解决上述问题?(我认为本书的目的是将p的值初始化为0,而不是null的地址.)

我在下面进行了试验但是在编译时都失败了:

试用1,添加constexpr:

constexpr int null = 0; 
int *p = null;
Run Code Online (Sandbox Code Playgroud)

试验2,加上const;

const int null = 0;
int *p = null;
Run Code Online (Sandbox Code Playgroud)

(我根据第4.11.2章其他隐式转换中的措辞进行了此试验:"常量整数值为0,文字nullptr可以转换为任何指针类型;")

先感谢您.(原因被问为一个新问题:这是一个新的问题,希望找到一个解决方案.还有另一个密切相关的问题,但没有给出建议的解决方案这个constexpr整数不是空指针常量吗?)

c++ constexpr c++11

5
推荐指数
1
解决办法
473
查看次数

constexpr的静态元组类成员有链接器错误

我有以下代码:

#include <iostream>
#include <tuple>

class T
{
    public:
        using Names = std::tuple<char const*, char const*>;
        static constexpr Names names {"First", "Second"};
};

int main()
{
    std::cout << std::get<0>(T::names);
}
Run Code Online (Sandbox Code Playgroud)

由于namesconstexpr我期待这个工作.但我收到一个链接器错误:

编译器:

> g++ --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 6.0 (clang-600.0.56) (based on LLVM 3.5svn)
Target: x86_64-apple-darwin14.0.0
Thread model: posix
Run Code Online (Sandbox Code Playgroud)

错误:

> g++ -std=c++1y pl.cpp
Undefined symbols for architecture x86_64:
  "T::names", referenced from:
      _main in pl-377031.o
ld: symbol(s) not found for architecture x86_64 …
Run Code Online (Sandbox Code Playgroud)

c++ constexpr c++11

5
推荐指数
1
解决办法
1001
查看次数

为什么我下面的第二个片段显示未定义的行为?

二者clangg++似乎是符合在C++标准的段落[expr.const]/5的最后一个版本.以下代码段为两个编译器打印11.查看实例:

#include <iostream>
void f(void) {
  static int n = 11;
  static int* temp = &n;
  static constexpr int *&&r = std::move(temp);

  std::cout << *r << '\n';
}

int main()
{
  f();
}
Run Code Online (Sandbox Code Playgroud)

根据我对本段的理解,两个编译器都应该打印2016下面的代码.但他们没有.因此,我必须得出结论,代码显示未定义的行为,因为clang打印任意数字并g++打印0.我想知道为什么它是UB,考虑到例如标准的N4527草案?实例.

#include <iostream>
void f(void) {
  static int n = 11;
  static int m = 2016;
  static int* temp = &n + 1;
  static constexpr int *&&r = std::move(temp);

  std::cout << …
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer constexpr c++17

5
推荐指数
1
解决办法
147
查看次数

在非`constexpr`上下文中的`constexpr`函数中使用lambda:clang vs gcc

请考虑以下代码(可在gcc.godbolt.org上获得):

template <typename TF>
constexpr auto fn_x(TF f)
{
    return f();
}

constexpr auto get_x()
{
    return fn_x([]{ return 0; });
}

int main()
{
    auto res = get_x();
}
Run Code Online (Sandbox Code Playgroud)

它在g ++ 5.3.x和更新版本(包括g ++ 6.xx)下编译.

它不能在clang ++ 3.7.x和更新版本下编译,并出现以下错误:

error: constexpr function never produces a constant expression [-Winvalid-constexpr]
constexpr auto get_x()
               ^
note: subexpression not valid in a constant expression
        return fn_x([]{ return 0; });                        
Run Code Online (Sandbox Code Playgroud)

使用gcc和clang编译代码的可能解决方案是使用"间接层" decltype,同时摆脱constexpr …

c++ lambda language-lawyer constexpr c++14

5
推荐指数
1
解决办法
231
查看次数