gpt4 book ai didi

c++ - 连接 vector 的 Constexpr 函数

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:06:54 26 4
gpt4 key购买 nike

我正在尝试初始化 const std::vector<std::string>基类的成员对象,其 vector 由从派生类向上传递的编译时字符串组成。派生类将定义 vector 中的一些字符串, vector 中的其余字符串将由派生类的子类(即从派生类派生的类)定义。

例如:

// +----------------+
// | ConfigBaseUnit |
// +----------------+
class ConfigBaseUnit
{
public:
ConfigBaseUnit(std::vector<std::string> &&fields);
virtual ~ConfigBaseUnit() = 0;

private:
const std::vector<std::string> field_vector;
};

ConfigBaseUnit::ConfigBaseUnit(std::vector<std::string> &&fields)
: field_vector(std::move(fields)) {
}
ConfigBaseUnit::~ConfigBaseUnit(){}

// +----------+
// | Ioconfig |
// +----------+
class Ioconfig : public ConfigBaseUnit
{
public:
Ioconfig(std::vector<std::string> &&fields);
virtual ~Ioconfig() {};
};

std::vector<std::string> & vect_concat(
std::vector<std::string> &&v1,
std::vector<std::string> &&v2 )
{
v1.insert(v1.end(), v2.begin(), v2.end());
return v1;
}

Ioconfig::Ioconfig(std::vector<std::string> &&fields)
: ConfigBaseUnit( std::move(
vect_concat({ "label", "protocol", "connected" }, std::move(fields))
)
) {
}

// +-------------------+
// | Ioconfig_Ethernet |
// +-------------------+
class Ioconfig_Ethernet : public Ioconfig
{
public:
Ioconfig_Ethernet();
virtual ~Ioconfig_Ethernet() final {};
};

Ioconfig_Ethernet::Ioconfig_Ethernet()
: Ioconfig( { "ip", "port" } ) {
}


这里,抽象基类 ConfigBaseUnit初始化其常量 field_vector成员及其类构造函数参数。

ConfigBaseUnit::ConfigBaseUnit(std::vector<std::string> &&fields) 
: field_vector(std::move(fields)) {
}

派生类Ioconfig想要 field_vector 的初始化始终包括这些项目:

{ "label", "protocol", "connected" }

但是field_vector还应包括 Ioconfig_Ethernet 发送的项目(源自 Ioconfig )。例如,Ioconfig_Ethernet传递这些内容以供包含:

{ "ip", "port" }

Ioconfig像这样在其构造函数中将它们联系在一起:

Ioconfig::Ioconfig(std::vector<std::string> &&fields)
: ConfigBaseUnit{ std::move(
vect_concat({ "label", "protocol", "connected" }, std::move(fields))
)
} {
}

Ioconfig构造函数使用函数 vect_concat(...)将字段合并到一个最终 vector 中,然后将其移动到基类。

vect_concat只是:

std::vector<std::string> & vect_concat(
std::vector<std::string> &&v1,
std::vector<std::string> &&v2 )
{
v1.insert(v1.end(), v2.begin(), v2.end());
return v1;
}

进入正题

这行得通,但我想要 vect_concat成为 constexpr 功能。最终,ConfigBaseUnit::field_vector 中的值应该在编译时定义。它的内容应该是固定的、硬编码的纯文本值,可以通过阅读代码轻松发现(即它们永远不会从文件或命令行参数等中读取)。

只是定义vect_concat作为constexpr不起作用,大概是因为 std::vector::insert 不是 constexpr。我该如何解决这个问题?


注意:输入上面的问题后,我发现声明 vect_concat作为模板,我可以将其设为 constexpr功能。

这个有效:

template <class V>
constexpr V & vect_concat(V &&v1, V &&v2)
{
v1.insert(v1.end(), v2.begin(), v2.end());
return v1;
}

这不是:

constexpr std::vector<std::string> & vect_concat(
std::vector<std::string> &&v1,
std::vector<std::string> &&v2 )
{
v1.insert(v1.end(), v2.begin(), v2.end());
return v1;
}

因此,我的问题(不幸的是,这些问题是在撰写本文的过程中演变而来的)是:

  1. 上面两个函数有什么区别,使模板版本编译和非模板版本失败?两种情况都使用 std::vector::insert ,这似乎不是一个 constexpr 函数。
  2. constexpr说明符在模板案例中被简单地忽略了?
  3. 使用模板版本是否就是我最初问题的答案?

最佳答案

  1. 这两个函数之间的区别[使模板版本可以编译...]是根据此处的标准定义的 [dcl.constexpr], §9.1.5.6 :

If the instantiated template specialization of a constexpr function template or member function of a class template would fail to satisfy the requirements for a constexpr function or constexpr constructor, that specialization is still a constexpr function or constexpr constructor, even though a call to such a function cannot appear in a constant expression.

  1. 正如您从标准中看到的那样,constexpr 不会被忽略,但是当您尝试将它用作常量时,它不应该编译。

  2. 总的来说,我会说这只是对您最初请求的回​​答,以防您使用 vect_concat() 一个 constexpr 的唯一原因是交付代码中的意图(本身就是一个有值(value)的事业!)。但是,如果在任何时候继续前进,您尝试将其称为句法常量,它会显示自己缺少 constexpr 本身的全部要点。

关于c++ - 连接 vector 的 Constexpr 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51752003/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com