我看过一些之前与
constexpr
相关的帖子,尤其是这篇:
我根据阅读该主题的理解是,
constexpr
表示可以在编译时完全确定的内存位置(对象、函数等)。
考虑以下简单代码:
//code.h
#ifndef CODE_H
#define CODE_H
#include<vector>
#include<numeric>
#include<cstddef>
#include<algorithm>
#include<iostream>
using std::vector;
using std::iota;
using std::size_t;
using std::for_each;
using std::cout;
using std::endl;
//template<typename T, constexpr size_t s, constexpr T min>
template<typename T, const size_t s, const T min>
class obj{
public:
obj();
obj(const obj&)=delete;
obj& operator=(const obj&)=delete;
void print();
protected:
private:
vector<T>v = vector<T>(s);
};
//template<typename T, constexpr size_t s, constexpr T min>
template<typename T, const size_t s, const T min>
obj<T,s,min>::obj(){
iota(v.begin(), v.end(), min);
}
//template<typename T, constexpr size_t s, constexpr T min>
template<typename T, const size_t s, const T min>
void obj<T,s,min>::print(){
for_each(v.begin(), v.end(), [](const T& t){cout << t << " ";});
cout << endl;
return;
}
#endif
//main.cpp
#include "code.h"
int main (){
obj<int,5,0> V;
V.print();
return 0;
}
在上面的
code.h
中,如果我使用constexpr
(在代码中注释掉)用模板头替换模板头,则编译会在第一次遇到模板头时停止,而g++ 11.3.1
使用-Wfatal-errors
和 -std=c++17
,有以下错误:
我
n file included from main.c:1:
code.h:17:22: error: a parameter cannot be declared ‘constexpr’
17 | template<typename T, constexpr size_t s, constexpr T min>
| ^~~~~~~~~
compilation terminated due to -Wfatal-errors.
请注意,我在 main.c 中使用
constexpr 5
和 constexpr 0
来初始化模板。我在模板头中使用 constexpr
的想法是限制模板的用户在初始化模板时使用编译时常量。如果我改用 const
,代码将编译并以预期输出运行。
那么,为什么在这种情况下
constexpr
不能与 const
互换?
constexpr
不允许在函数或模板参数上使用。
带有
constexpr
的对象声明意味着该声明有一个常量表达式的初始化程序,以便编译器在编译时始终知道对象的值作为常量,但参数不能有这样的初始化程序该参数是调用者的初始化程序。因此,它与 constexpr
作为变量声明上的顶级说明符没有任何类似的含义。