3

This Q&A tells that we cannot unstringify something in C/C++. For example:

int i = 1 TO_IDENTIFIER("+") 2;

CANNOT be expanded to

int i = 1 + 2;

So I'm now thinking about an alternative:

Keep a map that maps the "string literal" to the "operator function" and then invoke the corresponding operator.

But I don't know whether there is a way to put operation function into std::map as it seems that operator+ is not a unique name as a variable.

Here is the real-world problem I am encountered:

I have a token "$1 + $2" and I can parse them as strings

"$1" "+" "$2"

Then "$1" and "$2" are replaced with 2 objects whose type both are z3::expr. And I also need to replace "+" with the operation function whose declaration is:

friend z3::expr operator+(z3::expr const & a, z3::expr const & b);

Since there are other operators like -, <, I hope this can be done automatically. Firstly I define a type corresponding to the operator:

typedef z3::expr (*MyOperatorTy)(z3::expr const &a, z3::expr const &b);

Then std::unordered_map is generated:

  • with type info in the map:

    std::unordered_map<std::string, MyOperatorTy> strOpMap (
      {"+", z3::expr operator+(z3::expr const & a, z3::expr const & b)},
      ...
    );
    
  • Without type info(just like a normal function variable)

    std::unordered_map<std::string, MyOperatorTy> strOpMap (
      {"+", operator+},
      ...
    );
    

Neither works. I also tried std::function<z3::expr(expr const&, z3::expr const)> as the mapped_type, but still failed.

So is there any way to treat operator functions as a variable and call through function pointers?

Community
  • 1
  • 1
Hongxu Chen
  • 5,240
  • 2
  • 45
  • 85
  • Use `&` before a member function pointer. To disambiguate over overloads, cast (implicitly or explicitly). – Yakk - Adam Nevraumont Jul 31 '14 at 13:47
  • @chris But according to [cppreference](http://en.cppreference.com/w/cpp/utility/functional/plus) it's just like `operator+`, right? How can it solve my problem? Furthermore, there are other operators needing mapping such as "&&" so these basic function is not enough. – Hongxu Chen Jul 31 '14 at 13:55
  • @Yakk There is no member function here; and I just feel confused how to put the operator function into the `std::unordered_map`:-( – Hongxu Chen Jul 31 '14 at 13:57
  • 1
    @HongxuChen An operator function with a fixed set of arguments? `static_cast(&Namespace::operator+)` assuming you put `operator+` for your type in the same Namespace as your type (as you should). So `static_cast< z3::expr(*)(z3::expr const&, z3::exprt const&) >( &z3::operator+ )`. At least I think that should work. – Yakk - Adam Nevraumont Jul 31 '14 at 14:14
  • Thanks, that seems the answer. I find I need to additionally declare the operator+ inside namespace z3, as [this thread](http://stackoverflow.com/questions/16718166/friend-function-declaration-definition-inside-a-namespace) and then everything goes fine. – Hongxu Chen Aug 01 '14 at 02:41

1 Answers1

1

&foo is a problem when foo denotes an overload set. And in any sizeable program, operator+ will be overloaded. The problem can be resolved if there's a context in which &foo is used which allows overload resolution, such as assigning &foo to a variable with function pointer type. That type is then used for overload resolution.

In your case, however, you're tyring to populate an std::initializer_list. Any overload of operator+ can be on that list.

Luckily, another situation also allows overload resolution: a cast. So,

typedef z3::expr (*MyOperatorTy)(z3::expr const &a, z3::expr const &b);

#define STR(var) #var
#define z3Op(var) \
   static_cast<MyOperatorTy> (operator##var## (z3::expr const &a, z3::expr const &b))
#define StrOpPair(var) \
  { STR(var), z3Op(var) }
MSalters
  • 173,980
  • 10
  • 155
  • 350
  • Thanks for pointing that I should use `std::initializer_list`. I find that @Yakk 's may be right. Also, it seems that there are some issues when concat `operator` and `+`; I don't know why, so I add [another question](http://stackoverflow.com/questions/25072193/why-string-concat-macro-doesnt-work-for-this-case). – Hongxu Chen Aug 01 '14 at 02:59