Vcsn  2.4
Be Rational
nullableset.hh
Go to the documentation of this file.
1 #pragma once
2 
3 #include <memory>
4 #include <sstream>
5 
6 #include <boost/optional.hpp>
7 
8 #include <vcsn/alphabets/setalpha.hh> // intersect
9 #include <vcsn/core/kind.hh>
10 #include <vcsn/labelset/fwd.hh>
13 #include <vcsn/labelset/oneset.hh>
14 #include <vcsn/misc/escape.hh>
15 #include <vcsn/misc/functional.hh>
16 #include <vcsn/misc/raise.hh>
17 
18 namespace vcsn
19 {
20  namespace detail
21  {
28  template <typename LabelSet>
30  {
31  using labelset_t = LabelSet;
32  using value_t = std::pair<typename labelset_t::value_t, bool>;
33 
34  ATTRIBUTE_PURE
35  static constexpr value_t
36  one()
37  {
38  return value_t{labelset_t::special(), true};
39  }
40 
41  ATTRIBUTE_PURE
42  static constexpr value_t
44  {
45  return value_t{labelset_t::special(), false};
46  }
47 
48  template <typename Ls>
49  ATTRIBUTE_PURE
50  static std::enable_if_t<Ls::has_one(), bool>
51  is_one_(const value_t& l)
52  {
53  return std::get<1>(l) || Ls::is_one(get_value(l));
54  }
55 
56  template <typename Ls>
57  ATTRIBUTE_PURE
58  static std::enable_if_t<!Ls::has_one(), bool>
59  is_one_(const value_t& l)
60  {
61  return std::get<1>(l);
62  }
63 
64  ATTRIBUTE_PURE
65  static bool
66  is_one(const value_t& l)
67  {
68  return is_one_<labelset_t>(l);
69  }
70 
71  template <typename Value>
72  static Value
73  transpose(const labelset_t& ls, Value l)
74  {
75  // This is not robust enough: Value is word_t, then it's not
76  // valid to call is_one on it. Since I'm unsure of the future
77  // of nullableset, let's not waste time on this now.
78  if (is_one(l))
79  return l;
80  else
81  return {ls.transpose(get_value(l)), false};
82  }
83 
84  template <typename... Args>
85  static value_t
86  value(const labelset_t& ls, Args&&... args)
87  {
88  return {ls.value(std::forward<Args>(args)...), false};
89  }
90 
91  ATTRIBUTE_PURE
92  static typename labelset_t::value_t
94  {
95  return std::get<0>(v);
96  }
97  };
98 
105  template <typename GenSet>
106  struct nullable_helper<letterset<GenSet>>
107  {
108  using genset_t = GenSet;
110  using value_t = typename labelset_t::value_t;
111 
112  ATTRIBUTE_PURE
113  static constexpr value_t
115  {
116  return genset_t::special();
117  }
118 
119  ATTRIBUTE_PURE
120  static constexpr value_t
121  one()
122  {
123  return genset_t::one_letter();
124  }
125 
126  ATTRIBUTE_PURE
127  static bool
129  {
130  return l == one();
131  }
132 
133  template <typename Value>
134  static Value
135  transpose(const labelset_t& ls, const Value& l)
136  {
137  return ls.transpose(l);
138  }
139 
140  template <typename... Args>
141  static value_t
142  value(const labelset_t& ls, Args&&... args)
143  {
144  return ls.value(std::forward<Args>(args)...);
145  }
146 
147  ATTRIBUTE_PURE
148  static value_t
150  {
151  return v;
152  }
153  };
154  }
155 
157  template <typename LabelSet>
158  class nullableset
159  {
160  public:
161  using labelset_t = LabelSet;
162  using labelset_ptr = std::shared_ptr<const labelset_t>;
166 
167  using value_t = typename helper_t::value_t;
168  using letter_t = typename labelset_t::letter_t;
169  using word_t = typename labelset_t::word_t;
170 
171  private:
175 
176  public:
177  using genset_ptr = decltype(ls_->genset());
178  using genset_t = decltype(ls_->generators());
179 
180  public:
182  : ls_{ls}
183  {}
184 
185  nullableset(const labelset_t& ls = {})
186  : nullableset{std::make_shared<const labelset_t>(ls)}
187  {}
188 
189  static symbol sname()
190  {
191  static auto res = symbol{"nullableset<" + labelset_t::sname() + '>'};
192  return res;
193  }
194 
196  static nullableset make(std::istream& is)
197  {
198  // name: nullableset<lal_char(abc)>.
199  // ^^^^^^^^^^^^
200  // labelset
201  eat(is, "nullableset<");
202  auto ls = labelset_t::make(is);
203  eat(is, '>');
204  return {ls};
205  }
206 
210  bool open(bool o) const
211  {
212  return this->ls_->open(o);
213  }
214 
215  static constexpr bool
217  {
218  return true;
219  }
220 
221  static constexpr bool
223  {
224  return false;
225  }
226 
227  static constexpr bool
229  {
230  return labelset_t::is_letterized();
231  }
232 
233  static constexpr bool is_free()
234  {
235  return false;
236  }
237 
238  ATTRIBUTE_PURE
239  static constexpr value_t
240  one()
241  {
242  return helper_t::one();
243  }
244 
245  ATTRIBUTE_PURE
246  static bool
248  {
249  return helper_t::is_one(l);
250  }
251 
252  bool
254  {
255  return is_one(v) || ls_->is_valid(get_value(v));
256  }
257 
258  genset_ptr
259  genset() const
260  {
261  return ls_->genset();
262  }
263 
265  decltype(auto)
266  generators() const
267  {
268  return ls_->generators();
269  }
270 
271  value_t
273  {
274  return v;
275  }
276 
277  value_t
278  conv(oneset, typename oneset::value_t) const
279  {
280  return one();
281  }
282 
286  template <typename LabelSet_>
287  value_t
288  conv(const LabelSet_& ls, typename LabelSet_::value_t v) const
289  {
290  return value(ls_->conv(ls, v));
291  }
292 
293  const labelset_ptr labelset() const
294  {
295  return ls_;
296  }
297 
298  template <typename... Args>
299  value_t
300  value(Args&&... args) const
301  {
302  return helper_t::value(*ls_, std::forward<Args>(args)...);
303  }
304 
305  word_t
306  word(const value_t& l) const
307  {
308  if (is_one(l))
309  return make_wordset(*labelset()).one();
310  else
311  return ls_->word(get_value(l));
312  }
313 
315  auto static
317  -> decltype(labelset_t::letters_of(v))
318  {
319  return labelset_t::letters_of(v);
320  }
321 
324  auto
326  -> decltype(ls_->letters_of_padded(v, l))
327  {
328  return ls_->letters_of_padded(v, l);
329  }
330 
331  auto
333  -> decltype(this->letters_of_padded(this->word(v), l))
334  {
335  return letters_of_padded(word(v), l);
336  }
337 
339  static bool equal(const value_t& l, const value_t& r)
340  {
341  if (is_one(l))
342  return is_one(r);
343  else
344  return !is_one(r) && labelset_t::equal(get_value(l), get_value(r));
345  }
346 
348  static bool less(const value_t& l, const value_t& r)
349  {
350  if (is_one(r))
351  return false;
352  else if (is_one(l))
353  return true;
354  else
355  return labelset_t::less(get_value(l), get_value(r));
356  }
357 
359  value_t mul(const value_t& l, const value_t& r) const
360  {
361  if (is_one(r))
362  return l;
363  else if (is_one(l))
364  return r;
365  else
366  raise(*this, ": mul: invalid arguments: ",
367  to_string(*this, l), ", ", to_string(*this, r));
368  }
369 
371  value_t lgcd(const value_t& l, const value_t& r) const
372  {
373  if (equal(l, r))
374  return l;
375  else if (is_one(l) || is_one(r))
376  return one();
377  else
378  return value(ls_->lgcd(get_value(l), get_value(r)));
379  }
380 
382  value_t ldivide(const value_t& l, const value_t& r) const
383  {
384  if (auto res = maybe_ldivide(l, r))
385  return *res;
386  else
387  raise(*this, ": ldivide: invalid arguments: ",
388  to_string(*this, l), ", ", to_string(*this, r));
389  }
390 
391  boost::optional<value_t>
392  maybe_ldivide(const value_t& l, const value_t& r) const
393  {
394  if (equal(l, r))
395  return one();
396  else if (is_one(l))
397  return r;
398  else if (is_one(r))
399  return boost::none;
400  else if (auto res = ls_->maybe_ldivide(get_value(l), get_value(r)))
401  return value(*res);
402  else
403  return boost::none;
404  }
405 
407  value_t rdivide(const value_t& l, const value_t& r) const
408  {
409  if (auto res = maybe_rdivide(l, r))
410  return *res;
411  else
412  raise(*this, ": rdivide: invalid arguments: ",
413  to_string(*this, l), ", ", to_string(*this, r));
414  }
415 
416  boost::optional<value_t>
417  maybe_rdivide(const value_t& l, const value_t& r) const
418  {
419  if (equal(l, r))
420  return one();
421  else if (is_one(l))
422  return boost::none;
423  else if (is_one(r))
424  return l;
425  else if (auto res = ls_->maybe_rdivide(get_value(l), get_value(r)))
426  return value(*res);
427  else
428  return boost::none;
429  }
430 
431  static value_t
433  {
434  return helper_t::special();
435  }
436 
437  static bool
439  {
440  return !is_one(v) && labelset_t::is_special(get_value(v));
441  }
442 
443  static size_t size(const value_t& v)
444  {
445  return is_one(v) ? 0 : labelset_t::size(get_value(v));
446  }
447 
448  // FIXME: specialize for both implementation.
449  static size_t hash(const value_t& v)
450  {
451  // Do not use get_value when is_one. Let's hash one() as 0.
452  return is_one(v) ? 0 : labelset_t::hash(get_value(v));
453  }
454 
455  letter_t
456  get_letter(std::istream& i, bool quoted = true) const
457  {
458  return ls_->get_letter(i, quoted);
459  }
460 
462  value_t
463  conv(std::istream& i, bool quoted = true) const
464  {
465  // Check for '\e', otherwise pass it to the inner labelset.
466  if (i.good() && i.peek() == '\\')
467  {
468  i.ignore();
469  int c = i.peek();
470  if (c == 'e')
471  {
472  i.ignore();
473  return {};
474  }
475  else
476  i.unget();
477  }
478  return value(ls_->conv(i, quoted));
479  }
480 
490  template <typename Fun>
491  void convs(std::istream& i, Fun&& fun) const
492  {
493  ls_->convs(i,
494  [this,fun](const typename labelset_t::value_t& l)
495  {
496  fun(value(l));
497  });
498  }
499 
500  value_t conjunction(const value_t& l, const value_t& r) const
501  {
502  if (is_one(l) && is_one(r))
503  return l;
504  else if (!is_one(l) && !is_one(r))
505  return ls_->conjunction(get_value(l), get_value(r));
506  else
507  raise(*this,
508  ": conjunction: invalid operation (lhs and rhs are not equal): ",
509  to_string(*this, l), ", ", to_string(*this, r));
510  }
511 
513  std::ostream&
514  print(const value_t& l, std::ostream& o = std::cout,
515  format fmt = {}) const
516  {
517  if (is_one(l))
518  o << (fmt == format::latex ? "\\varepsilon"
519  : fmt == format::utf8 ? "ε"
520  : "\\e");
521  else
522  ls_->print(get_value(l), o, fmt);
523  return o;
524  }
525 
526  value_t
527  zero() const
528  {
529  return value(ls_->zero());
530  }
531 
532  bool
533  is_zero(const value_t& v) const
534  {
535  return !is_one(v) && ls_->is_zero(get_value(v));
536  }
537 
538  bool
539  is_letter(const value_t& v) const
540  {
541  return !is_one(v) && ls_->is_letter(get_value(v));
542  }
543 
545  template <typename Value>
546  Value
547  transpose(const Value& l) const
548  {
549  return helper_t::transpose(*ls_, l);
550  }
551 
553  std::ostream&
554  print_set(std::ostream& o, format fmt = {}) const
555  {
556  switch (fmt.kind())
557  {
558  case format::latex:
559  o << "(";
560  ls_->print_set(o, fmt);
561  o << ")^?";
562  break;
563 
564  case format::sname:
565  o << "nullableset<";
566  ls_->print_set(o, fmt);
567  o << '>';
568  break;
569 
570  case format::text:
571  case format::utf8:
572  ls_->print_set(o, fmt);
573  o << '?';
574  break;
575 
576  case format::raw:
577  assert(0);
578  break;
579  }
580 
581  return o;
582  }
583 
585  static typename labelset_t::value_t
586  get_value(const value_t& v)
587  {
588  assert(!is_one(v));
589  return helper_t::get_value(v);
590  }
591  };
592 
593  namespace detail
594  {
596  template <typename LabelSet>
597  struct letterized_traits<nullableset<LabelSet>>
598  {
599  using traits = letterized_traits<LabelSet>;
600  static constexpr bool is_letterized = traits::is_letterized;
601 
602  using labelset_t = typename traits::labelset_t;
603 
604  static labelset_t labelset(const nullableset<LabelSet>& ls)
605  {
606  return make_letterized(*ls.labelset());
607  }
608  };
609 
611  template <typename LabelSet>
612  struct nullableset_traits<nullableset<LabelSet>>
613  {
614  using type = nullableset<LabelSet>;
615  static type value(const nullableset<LabelSet>& ls)
616  {
617  return ls;
618  }
619  };
620 
621  template <typename LabelSet>
622  struct proper_traits<nullableset<LabelSet>>
623  {
624  using type = LabelSet;
625  static type value(const nullableset<LabelSet>& ls)
626  {
627  return *ls.labelset();
628  }
629  };
630 
632  template <typename LabelSet>
633  struct law_traits<nullableset<LabelSet>>
634  {
635  using type = law_t<LabelSet>;
636  static type value(const nullableset<LabelSet>& ls)
637  {
638  return make_wordset(*ls.labelset());
639  }
640  };
641 
642  /*-------.
643  | Join. |
644  `-------*/
645 
647  template <typename LS>
648  struct join_impl<oneset, LS,
649  std::enable_if_t<!LS::has_one()>>
650  {
651  using type = nullableset<LS>;
652  static type join(const oneset&, const LS& ls)
653  {
654  return {ls};
655  }
656  };
657 
659  template <typename LS>
660  struct join_impl<oneset, LS,
661  std::enable_if_t<LS::has_one()>>
662  {
663  using type = LS;
664  static type join(const oneset&, const LS& ls)
665  {
666  return ls;
667  }
668  };
669 
671  template <typename LS1, typename LS2>
672  struct join_impl<nullableset<LS1>, LS2>
673  {
674  using type = nullableset<join_t<LS1, LS2>>;
675  static type join(const nullableset<LS1>& ls1, const LS2& ls2)
676  {
677  return {::vcsn::join(*ls1.labelset(), ls2)};
678  }
679  };
680 
685  template <typename LS1, typename LS2>
686  struct join_impl<nullableset<LS1>, nullableset<LS2>>
687  {
688  using type = nullableset<join_t<LS1, LS2>>;
689  static type join(const nullableset<LS1>& ls1,
690  const nullableset<LS2>& ls2)
691  {
692  return {::vcsn::join(*ls1.labelset(), *ls2.labelset())};
693  }
694  };
695  }
696 
697  /*-------.
698  | Meet. |
699  `-------*/
700 
701 #define DEFINE(Lhs, Rhs, Res) \
702  template <typename GenSet> \
703  Res \
704  meet(const Lhs& lhs, const Rhs& rhs) \
705  { \
706  return {set_intersection(*lhs.genset(), *rhs.genset())}; \
707  }
708 
710  DEFINE(nullableset<letterset<GenSet>>,
711  nullableset<letterset<GenSet>>, nullableset<letterset<GenSet>>);
712 
713  DEFINE(letterset<GenSet>,
714  nullableset<letterset<GenSet>>, nullableset<letterset<GenSet>>);
715 
716  DEFINE(nullableset<letterset<GenSet>>,
717  letterset<GenSet>, nullableset<letterset<GenSet>>);
718 
719  template <typename Lls, typename Rls>
720  nullableset<meet_t<Lls, Rls>>
721  meet(const nullableset<Lls>& lhs, const nullableset<Rls>& rhs)
722  {
723  return nullableset<meet_t<Lls, Rls>>{meet(*lhs.labelset(),
724  *rhs.labelset())};
725  }
726 
727 #undef DEFINE
728 
729 
730  /*----------------.
731  | random_label. |
732  `----------------*/
733 
735  template <typename LabelSet,
736  typename RandomGenerator = std::default_random_engine>
737  typename nullableset<LabelSet>::value_t
738  random_label(const nullableset<LabelSet>& ls,
739  RandomGenerator& gen = RandomGenerator())
740  {
741  // FIXME: the proportion should be controllable.
742  auto dis = std::bernoulli_distribution(0.5);
743  if (dis(gen) || ls.generators().empty())
744  return ls.one();
745  else
746  return ls.value(random_label(*ls.labelset(), gen));
747  }
748 }
char eat(std::istream &is, char c)
Check lookahead character and advance.
Definition: stream.cc:90
Print as a parsable type string.
Definition: format.hh:26
static constexpr bool is_free()
Definition: nullableset.hh:233
return res
Definition: multiply.hh:398
Implementation of labels are ones: there is a single instance of label.
Definition: oneset.hh:16
letter_t get_letter(std::istream &i, bool quoted=true) const
Definition: nullableset.hh:456
void convs(std::istream &i, Fun &&fun) const
Process a label class.
Definition: nullableset.hh:491
decltype(ls_->generators()) genset_t
Definition: nullableset.hh:178
Print for LaTeX.
Definition: format.hh:22
static ATTRIBUTE_PURE std::enable_if_t< Ls::has_one(), bool > is_one_(const value_t &l)
Definition: nullableset.hh:51
static ATTRIBUTE_PURE constexpr value_t one()
Definition: nullableset.hh:121
static Value transpose(const labelset_t &ls, const Value &l)
Definition: nullableset.hh:135
bool is_special(const Aut &aut, transition_t_of< Aut > t)
Whether this transition is from pre or to post.
Definition: automaton.hh:228
static symbol sname()
Definition: nullableset.hh:189
static constexpr bool is_expressionset()
Definition: nullableset.hh:222
bool value_t
Definition: oneset.hh:20
value_t value(Args &&...args) const
Value constructor.
Definition: letterset.hh:83
value_t zero() const
Definition: nullableset.hh:527
An input/output format for valuesets.
Definition: format.hh:13
weightset_mixin< detail::r_impl > r
Definition: fwd.hh:54
Provide a variadic mul on top of a binary mul(), and one().
Definition: fwd.hh:46
labelset_ptr ls_
The wrapped LabelSet.
Definition: nullableset.hh:174
boost::flyweight< std::string, boost::flyweights::no_tracking, boost::flyweights::intermodule_holder > symbol
An internalized string.
Definition: symbol.hh:23
letter_t value_t
Definition: letterset.hh:33
typename labelset_t::letter_t letter_t
Definition: nullableset.hh:168
static size_t hash(const value_t &v)
Definition: nullableset.hh:449
static Value transpose(const labelset_t &ls, Value l)
Definition: nullableset.hh:73
Definition: a-star.hh:8
nullableset(const labelset_ptr &ls)
Definition: nullableset.hh:181
std::shared_ptr< const labelset_t > labelset_ptr
Definition: nullableset.hh:162
size_t size(const ExpSet &rs, const typename ExpSet::value_t &r)
Print as rich UTF-8 text, escaped.
Definition: format.hh:30
static nullableset make(std::istream &is)
Build from the description in is.
Definition: nullableset.hh:196
bool open(bool o) const
Whether unknown letters should be added, or rejected.
Definition: nullableset.hh:210
static bool is_special(const value_t &v)
Definition: nullableset.hh:438
value_t conv(oneset, typename oneset::value_t) const
Definition: nullableset.hh:278
std::ostream & print_set(std::ostream &o, format fmt={}) const
Print labelset description.
Definition: nullableset.hh:554
std::enable_if_t<!is_letterized_t< labelset_t_of< Aut > >{}, bool > is_letterized(const Aut &aut)
Definition: letterize.hh:161
static size_t size(const value_t &v)
Definition: nullableset.hh:443
static value_t value(const labelset_t &ls, Args &&...args)
Definition: nullableset.hh:142
Implementation of labels are nullables (letter or empty).
Definition: fwd.hh:14
typename helper_t::value_t value_t
Definition: nullableset.hh:167
bool is_valid(value_t v) const
Definition: nullableset.hh:253
static value_t special()
Definition: nullableset.hh:432
static ATTRIBUTE_PURE bool is_one(value_t l)
Definition: nullableset.hh:128
static ATTRIBUTE_PURE constexpr value_t one()
Definition: nullableset.hh:36
std::pair< typename labelset_t::value_t, bool > value_t
Definition: nullableset.hh:32
static bool equal(const value_t &l, const value_t &r)
Whether l == r.
Definition: nullableset.hh:339
value_t rdivide(const value_t &l, const value_t &r) const
Compute l / r.
Definition: nullableset.hh:407
value_t conjunction(const value_t &l, const value_t &r) const
Definition: nullableset.hh:500
static ATTRIBUTE_PURE bool is_one(value_t l)
Definition: nullableset.hh:247
static ATTRIBUTE_PURE labelset_t::value_t get_value(const value_t &v)
Definition: nullableset.hh:93
boost::optional< value_t > maybe_ldivide(const value_t &l, const value_t &r) const
Definition: nullableset.hh:392
value_t value(Args &&...args) const
Definition: nullableset.hh:300
static constexpr bool is_letterized()
Definition: nullableset.hh:228
value_t conv(const LabelSet_ &ls, typename LabelSet_::value_t v) const
Conversion from another type: first by the wrapped labelset, and then by our wrappers (in case the wr...
Definition: nullableset.hh:288
static ATTRIBUTE_PURE std::enable_if_t<!Ls::has_one(), bool > is_one_(const value_t &l)
Definition: nullableset.hh:59
return v
Definition: multiply.hh:361
ATTRIBUTE_PURE auto transpose(Args &&...args) const -> decltype(this->genset() -> transpose(std::forward< Args >(args)...))
static ATTRIBUTE_PURE constexpr value_t special()
Definition: nullableset.hh:114
Implementation of labels are letters.
Definition: fwd.hh:10
Value transpose(const Value &l) const
Mirror label.
Definition: nullableset.hh:547
symbol sname()
Definition: name.hh:65
typename labelset_t::word_t word_t
Definition: nullableset.hh:169
std::string to_string(direction d)
Conversion to string.
Definition: direction.cc:7
static ATTRIBUTE_PURE bool is_one(const value_t &l)
Definition: nullableset.hh:66
static bool less(const value_t &l, const value_t &r)
Whether l < r.
Definition: nullableset.hh:348
const labelset_ptr labelset() const
Definition: nullableset.hh:293
static ATTRIBUTE_PURE value_t get_value(const value_t &v)
Definition: nullableset.hh:149
static auto letters_of(const word_t &v) -> decltype(labelset_t::letters_of(v))
Prepare to iterate over the letters of v.
Definition: nullableset.hh:316
decltype(auto) generators() const
The generators. Meaningful for labelsets only.
Definition: nullableset.hh:266
static ATTRIBUTE_PURE constexpr value_t one()
Definition: nullableset.hh:240
auto letters_of_padded(const word_t &v, letter_t l) const -> decltype(ls_->letters_of_padded(v, l))
Prepare to iterate over the letters of v.
Definition: nullableset.hh:325
value_t lgcd(const value_t &l, const value_t &r) const
The longest common prefix.
Definition: nullableset.hh:371
value_t conv(self_t, value_t v) const
Definition: nullableset.hh:272
static labelset_t::value_t get_value(const value_t &v)
The (inner) value when it (the outer value) is not one.
Definition: nullableset.hh:586
word_t word(const value_t &l) const
Definition: nullableset.hh:306
value_t ldivide(const value_t &l, const value_t &r) const
Compute l \ r = l^{-1}r.
Definition: nullableset.hh:382
bool is_letter(const value_t &v) const
Definition: nullableset.hh:539
auto letters_of_padded(value_t v, letter_t l) const -> decltype(this->letters_of_padded(this->word(v), l))
Definition: nullableset.hh:332
decltype(ls_->genset()) genset_ptr
Definition: nullableset.hh:177
bool is_zero(const value_t &v) const
Definition: nullableset.hh:533
genset_ptr genset() const
Definition: nullableset.hh:259
std::ostream & print(const value_t &l, std::ostream &o=std::cout, format fmt={}) const
Print label to stream.
Definition: nullableset.hh:514
static ATTRIBUTE_PURE constexpr value_t special()
Definition: nullableset.hh:43
Add support for an empty word to a LabelSet that does not provide such special label to this end...
Definition: nullableset.hh:29
value_t mul(const value_t &l, const value_t &r) const
The concatenation.
Definition: nullableset.hh:359
nullableset(const labelset_t &ls={})
Definition: nullableset.hh:185
value_t conv(std::istream &i, bool quoted=true) const
Read a label from a stream.
Definition: nullableset.hh:463
static constexpr bool has_one()
Definition: nullableset.hh:216
static value_t value(const labelset_t &ls, Args &&...args)
Definition: nullableset.hh:86
law_t< LabelSet > make_wordset(const LabelSet &ls)
The wordset of a labelset.
Definition: labelset.hh:260
boost::optional< value_t > maybe_rdivide(const value_t &l, const value_t &r) const
Definition: nullableset.hh:417