为什么在这种情况下 constexpr 不能与 const 互换?

问题描述 投票:0回答:1

我看过一些之前与

constexpr
相关的帖子,尤其是这篇:

constexpr 和 const 有什么区别?

我根据阅读该主题的理解是,

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
互换?

c++ templates c++17 constants constexpr
1个回答
0
投票

constexpr
不允许在函数或模板参数上使用。

带有

constexpr
的对象声明意味着该声明有一个常量表达式的初始化程序,以便编译器在编译时始终知道对象的值作为常量,但参数不能有这样的初始化程序该参数是调用者的初始化程序。因此,它与
constexpr
作为变量声明上的顶级说明符没有任何类似的含义。

© www.soinside.com 2019 - 2024. All rights reserved.