Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 5942565
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 22, 20262026-05-22T16:16:17+00:00 2026-05-22T16:16:17+00:00

I have a sfinae class that tests whether a class is a parser rule

  • 0

I have a sfinae class that tests whether a class is a parser rule (AXE parser generator library).
The axe::is_rule<P>::value should evaluate to true iff P satisfies parser rule requirements. A parser rule must have one of the following member functions, taking a pair of iterators and returning axe::result<Iterator>:

template<class Iterator>
axe::result<Iterator> P::operator()(Iterator, Iterator);

, or its specialization, or non-template for some type CharT

axe::result<CharT*> P::operator()(CharT*, CharT*);

, or const versions of the above. Theoretically, there can be more than one overloaded operator(), though in practice a test for a single operator() with one of the above signatures would suffice.

Unfortunately, current implementation of is_rule takes care of only some, but not all cases. There are some unfortunate classes, that fail the is_rule test:

#define AXE_ASSERT_RULE(T)\
    static_assert(axe::is_rule<typename std::remove_reference<T>::type>::value, \
    "type '" #T "' is not a rule");

For example, the following unfortunate types fail the test:

struct unfortunate 
{ 
   axe::result<const unsigned char*> 
   operator()(const unsigned char*, const unsigned char*); 
};

AXE_ASSERT_RULE(unfortunate);

// or same using lambda
auto unfortunate1 = [](const unsigned char*, const unsigned char*)
->axe::result<const unsigned char*> {};
AXE_ASSERT_RULE(decltype(unfortunate1));


typedef std::vector<char>::iterator vc_it;
struct unfortunate2 { axe::result<vc_it> operator()(vc_it, vc_it) const; };
AXE_ASSERT_RULE(unfortunate2);

typedef axe::result<const char*> (unfortunate3)(const char*, const char*);
AXE_ASSERT_RULE(unfortunate3);

struct rule { template<class I> axe::result<I> operator()(I, I); };
class unfortunate4 : public rule {};
AXE_ASSERT_RULE(unfortunate4);

Current solution in AXE is to wrap those in a forwarding wrapper (class r_ref_t), which, of course, creates syntactic warts (after all, parser generator is all about syntactic sugar).

How would you modify the sfinae test in is_rule to cover the unfortunate cases above?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-22T16:16:17+00:00Added an answer on May 22, 2026 at 4:16 pm

    I think the API of is_rule is not sufficient. For example unfortunate is a rule only if used with iterators of type const unsigned char*. If you use unfortunate with const char*, then it doesn’t work, and is thus not a rule, right?

    That being said, if you change the API to:

    template <class R, class It> struct is_rule;
    

    then I think this is doable in C++11. Below is a prototype:

    #include <type_traits>
    
    namespace axe
    {
    
    template <class It>
    struct result
    {
    };
    
    }
    
    namespace detail
    {
    
    struct nat
    {
        nat() = delete;
        nat(const nat&) = delete;
        nat& operator=(const nat&) = delete;
        ~nat() = delete;
    };
    
    struct any
    {
        any(...);
    
        nat operator()(any, any) const;
    };
    
    template <class T>
    struct wrap
        : public any,
          public T
    {
    };
    
    template <bool, class R, class It>
    struct is_rule
    {
         typedef typename std::conditional<std::is_const<R>::value,
                                          const wrap<R>,
                                          wrap<R>>::type W;
    
       typedef decltype(
                    std::declval<W>()(std::declval<It>(), std::declval<It>())
                        ) type;
    
        static const bool value = std::is_convertible<type, axe::result<It>>::value;
    };
    
    template <class R, class It>
    struct is_rule<false, R, It>
    {
        static const bool value = false;
    };
    
    }  // detail
    
    template <class R, class It>
    struct is_rule
        : public std::integral_constant<bool,
                             detail::is_rule<std::is_class<R>::value, R, It>::value>
    {
    };
    
    struct unfortunate 
    { 
       axe::result<const unsigned char*> 
       operator()(const unsigned char*, const unsigned char*); 
    };
    
    #include <iostream>
    
    int main()
    {
        std::cout << is_rule<unfortunate, const unsigned char*>::value << '\n';
        std::cout << is_rule<unfortunate, const char*>::value << '\n';
    }
    

    For me this prints out:

    1
    0
    

    I made the rule slightly more lax than you specified: The return type only has to be implicitly convertible to axe::result<It>. If you really want it to be exactly axe::result<It> then just sub in std::is_same where I used std::is_convertible.

    I also made is_rule derive from std::integral_constant. This can be very convenient for tag dispatching. E.g.:

    template <class T>
    void imp(T, std::false_type);
    
    template <class T>
    void imp(T, std::true_type);
    
    template <class T>
    void foo(T t) {imp(t, is_rule<T, const char*>());}
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

In C++0x SFINAE rules have been simplified such that any invalid expression or type
I have an SFINAE test for checking if an class has a function. The
I have a class with a template parameter which should decide which of two
I've been working on some solutions for some questions that have been recently posted
I'm trying to use SFINAE to detect if a class has an overloaded member
After reading the answer to this question , I learned that SFINAE can be
I have a header file, whose functionality relies heavily on the success of SFINAE.
Have a photography site that I want to prevent image copying from. How can
Let's say I have some templated class depending on type T . T could
I have a class ( Voxel ) with subclasses which may or may not

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.