我的理解是:
看来像下面这样的东西不应该编译,事实上在我的编译器上它不编译。
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> …
有没有办法编写一个 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) 我尝试让成员函数要求静态 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是在同一个类中声明的吗?或者我有某种语法错误?
第四次编辑:原始问题标题是:
为什么
constexpr说明符不允许非空std::vector?
正如 @Barry 指出的,这个标题与C++20 constexpr vector and string not working重复。但我的问题描述有所不同:我constexpr vector在constevalfunction而不是正常的运行时 function 或constexprfunction中分配。
据我所知,在编译时计算期间,只允许瞬时分配,正如 @Barry 在链接问题中回答的那样。
我感到困惑的是:对于consteval功能:
constexpr vector作为局部变量,将在编译时释放我在下面的其他编辑回答了这个困惑。
-----------------以下是原问题描述----------
为什么下面的代码不能编译:
consteval int foo() {
constexpr std::vector<int> vec{1};
return vec[0];
}
Run Code Online (Sandbox Code Playgroud)
据我所知,只要分配和释放都发生在编译时,就可以在编译时使用 和std::vector。std::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++ 11标准指定的numeric_limits<T>::min和max必须是能够在模板或使用常数表达式static_assert?
更一般地说,如何根据标准找到常量表达式的函数列表?
我正在尝试使用外部链接创建名称空间范围常量
// 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++ 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整数不是空指针常量吗?)
我有以下代码:
#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)
由于names是constexpr我期待这个工作.但我收到一个链接器错误:
编译器:
> 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) 二者clang并g++似乎是符合在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) 请考虑以下代码(可在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 …