C++;具有可选参数的构造函数 我是C++的新手,我正在尝试创建一个类层次结构,其中每个类代表一个模式文档中的节点,认为JSON模式。看一下例如a的表示。Astring可以有三个可选约束 最小长度 最大长度 模式

C++;具有可选参数的构造函数 我是C++的新手,我正在尝试创建一个类层次结构,其中每个类代表一个模式文档中的节点,认为JSON模式。看一下例如a的表示。Astring可以有三个可选约束 最小长度 最大长度 模式,c++,class,c++14,optional-parameters,C++,Class,C++14,Optional Parameters,此外,字符串是一个类型,因此有一个基类表示一个类型,所有类型(布尔型,数字,…)都从该类型继承。现在,实现这一点的一种方法是写 struct Type { const std::string m_name; Type(const std::string& name) : m_name{name} {} virtual X Serialize() const { //... } }; struct String : Type { const int

此外,
字符串
是一个
类型
,因此有一个基类表示一个
类型
,所有类型(
布尔型
数字
)都从该类型继承。现在,实现这一点的一种方法是写

struct Type {
  const std::string m_name;

  Type(const std::string& name)
  : m_name{name}
  {}

  virtual X Serialize() const {
    //...
  }
};

struct String : Type {
  const int m_max_len;
  const int m_min_len;
  const std::string m_pattern;

  String(int min_len, int max_len, const std::string& pattern)
  : Type("string")
  , m_min_len(min_len)
  , m_max_len(max_len)
  , m_pattern(pattern)
  {}

  X Serialize() const override {
    // If min_length was not set then it should be omitted from the serialized output.
  }
};
字符串
实现不会使约束成为可选的。怎么办

选项:

  • 可以采用一种策略,将默认构造函数参数设置为一些“非法”值,如
    INT\u MIN
    (在这种情况下有效,因为长度不能为负),但在一般情况下不起作用。很可能所有可能的整数都是合法值,
    模式
    参数也是如此
  • 对于可选参数的每个可能排列,您不希望有不同的构造函数。在这种情况下,有三个可选值将产生不同的构造函数。编译器也无法区分构造函数
    String(int-min\u-length)
    String(int-max\u-length)
  • 有可能做类似的事情

    String(int*min\u length=nullptr,int*max\u length=nullptr,const std::String*nullptr)


    但是您必须使用
    new
    /
    delete
    或为设置的参数提供左值
  • 最后,每个成员都可以是
    std::unique\u ptr


    字符串(std::unique\u ptr min\u value nullptr,std::unique\u ptr max\u value=nullptr,std::unique\u ptr pattern=nullptr)


    但是,在创建
    String
    的实例时,最终会得到相当复杂的调用。此外,如果实现类型为s的容器,它可能有自己的可选参数,那么很快就会失控

最后,代码必须与C++14兼容。

您只需使用
std::optional

String(const std::optional<int> &min_len, const std::optional<int> &max_len, 
       const std::optional<std::string> &pattern);

Type *type = new String(5, {}, std::nullptr); // last 2 parameters are omitted.
字符串(常量标准::可选和最小长度,常量标准::可选和最大长度,
常量标准::可选和模式);
Type*Type=新字符串(5,{},std::nullptr);//省略最后2个参数。
对于C++14,您可以使用其他开放源代码库中存在的类似构造(例如,
boost::optional
folly::optional
)。

您尝试过使用A吗(从C++17开始)?
我知道您提到需要使用与C++14兼容的代码,但是有一个可用的方法。

如果不能使用std::optional,您可以编写自己的类,该类可以包含值,也可以不包含值。它不像很多代码。可以使其接口像std::optioal一样,或者可以使其有所不同,重要的是数据:

class OptInt {
    bool set_;
    int value_;
public:
    OptInt() : set_(false) , value_(0) {}
    OptInt(int v) : set_(true), value_(v) {}
    // can add other ways how to create it

    bool isSet() const {return set_;}
    int get() const {if (!set_) throw 666; return value_;}
    // can add other operations you want to it.
};

然后您可以使用这种默认构造的OptInt作为默认参数,因此它不会被设置,但如果调用者提供int参数,那么它就会被设置。

我没有信誉点来评论@Kostas

为了与C++14兼容,您可以尝试具有可选名称空间的实验名称空间(如果它可用/在您的编译器上工作)

#包括
然后你可以用

String(std::experimental::optional<int> &min_len,.....)
min_len.value_or(-1)
String(标准::实验::可选和最小长度,…)
最小长度值或(-1)

我不确定你的问题到底是什么。在这里不使用多态性会容易得多,我认为“因为长度不能为负”--当值不能为负时,你应该使用无符号的整数,而不是普通的
int
。我认为你应该为每个参数创建一个类,因此,您的调用看起来像
String(MinLength::default(),MaxLength(42),String)
。你也可能会从中得到启发。为什么
Type
与你的问题相关?当我跳过你的问题中涉及类型层次结构的部分时,这和我阅读全文时一样有意义。似乎这个问题应该集中在具有可选参数的类上,而不考虑多态性。我在多态性讨论中看到的一个相关细节是,您需要区分“未给定参数”和“给定参数未施加限制”(后者的一个示例是将最小长度设置为0)。你可能想在文本中提到这个细节。OP说“必须与C++14兼容”,而
std::optional
是C++17。我认为通过常量引用传递
std::optional
没有任何好处。用户可能不会提供类型为
std::optional
的参数,并且将创建临时参数。这实际上与传递值相同。但是,您可能希望通过const引用传递字符串参数(不是围绕其副本构建的可选参数)。在这种情况下,您需要的是
std::optional pattern
。用户可以传递
std::nullopt
。即使未设置/提供最低版本,也会创造价值,而改进版本(st std one)则不会。@Jarod42说“我是C++新手”的人也许不应该弄乱放置新闻,因为它需要获得一点点性能。如果需要的话,可以在以后添加。我没有要求提供更好(更复杂)的实现,只是告知如果需要可以改进。(例如,OP可能有非默认可构造的类型)。这暗示了@generic_opto_guy在原始帖子中给出的答案。我想我会尝试这种方法。谢谢
String(std::experimental::optional<int> &min_len,.....)
min_len.value_or(-1)