Skip to content

Instantly share code, notes, and snippets.

@Nekrolm
Created January 11, 2020 15:12
Show Gist options
  • Save Nekrolm/8e8dd870b1b600be1adbd5429f96551d to your computer and use it in GitHub Desktop.
Save Nekrolm/8e8dd870b1b600be1adbd5429f96551d to your computer and use it in GitHub Desktop.
c++20 concepts example
#include <type_traits>
template <class From, class To>
concept is_convertible = requires(From f){
{ static_cast<To>(f) } -> To;
};
template <typename Fst>
concept BaseFst = requires {
typename Fst::Arc;
typename Fst::StateId;
} && requires(Fst fst, typename Fst::StateId s) {
{ fst.Start() } -> typename Fst::StateId;
{ fst.Final(s)};
};
template <class Fst>
concept ExpandedFst = BaseFst<Fst> &&
requires(Fst fst,
typename Fst::StateId s) {
{ fst.NumStates() } -> is_convertible<std::size_t>;
{ fst.NumArcs(s) } -> is_convertible<std::size_t>;
};
template <class AIter, class Fst>
concept ArcIterator = BaseFst<Fst> && requires(AIter iter,
Fst fst,
typename Fst::StateId s) {
{ iter.Done() } -> bool;
{ iter.Value() } -> is_convertible<typename Fst::Arc>;
{ iter.Next() };
{ AIter(fst, s) };
};
template <class SIter, class Fst>
concept StateIterator = BaseFst<Fst> && requires(SIter iter,
Fst fst) {
{ iter.Done() } -> bool;
{ iter.Value() } -> is_convertible<typename Fst::StateId>;
{ iter.Next() };
{ SIter(fst) };
};
template <class Fst>
concept IterableFst = BaseFst<Fst> &&
requires{
typename Fst::ArcIterator;
typename Fst::StateIterator;
}
&& ArcIterator<typename Fst::ArcIterator, Fst>
&& StateIterator<typename Fst::StateIterator, Fst>;
//----------------------
//----------------------
// ---- TEST -----------
template <BaseFst FstT>
struct AIterTpl {
AIterTpl(const FstT&, typename FstT::StateId s); // ctor;
const typename FstT::Arc& Value();
void Next();
bool Done();
};
template <BaseFst FstT>
struct SIterTpl {
SIterTpl(const FstT&); // ctor;
int Value();
void Next();
bool Done();
};
class VectorFst {
public:
struct Arc {
int nextstate;
};
using StateId = int;
StateId Start() { return 0; };
float Final(StateId) {return 0; };
int NumStates() {return 0;};
int NumArcs(StateId s) {return 0;};
// forward declaration
// we cannot use S/AIterTpl here due to concept constraint:
// VectorFst must be a complete type before conceps checking;
// so definition is placed outside.
struct ArcIterator;
struct StateIterator;
};
struct VectorFst::ArcIterator : AIterTpl<VectorFst>
{ using AIterTpl<VectorFst>::AIterTpl; };
struct VectorFst::StateIterator : SIterTpl<VectorFst>
{ using SIterTpl<VectorFst>::SIterTpl; };
template <class Fst> requires BaseFst<Fst>
void check_base(const Fst& fst){}
template <class Fst> requires ExpandedFst<Fst>
void check_expanded(const Fst& fst){}
template <class Fst> requires IterableFst<Fst>
void check_iterable(const Fst& fst){}
class NotFst {
public:
};
int main() {
VectorFst fst;
NotFst nfst;
check_base(fst);
check_expanded(fst);
check_iterable(fst);
// check(nfst);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment