Is it possible to put a unique_ptr in the Any class of the C++ runtime of Antlr4.7?

241 views
Skip to first unread message

Maurice van der Pot

unread,
May 1, 2017, 3:41:38 PM5/1/17
to antlr-discussion
I'm making a visitor that constructs the object model for my application after parsing something from file.
This object model includes unique_ptrs to hold ownership for some objects. When returning these from visitor methods, I get compilation errors having to do with unique_ptrs being put in the Any class.
(FYI: I only recently learned about unique_ptr and move semantics).

Here's a minimal example that shows the error:

#include <memory>
#include "antlr4-runtime.h"

int main()
{
  std::unique_ptr<int *> a;
  antlrcpp::Any b(std::move(a));
  return 0;
}

The error I get with clang-3.9.1 looks like this (but gcc's is similar):

In file included from testje.cpp:2:
In file included from antlr4-cpp-runtime-prefix/include/antlr4-runtime/antlr4-runtime.h:30:
In file included from antlr4-cpp-runtime-prefix/include/antlr4-runtime/InterpreterRuleContext.h:8:
In file included from antlr4-cpp-runtime-prefix/include/antlr4-runtime/ParserRuleContext.h:8:
In file included from antlr4-cpp-runtime-prefix/include/antlr4-runtime/RuleContext.h:8:
In file included from antlr4-cpp-runtime-prefix/include/antlr4-runtime/tree/ParseTree.h:8:
antlr4-cpp-runtime-prefix/include/antlr4-runtime/support/Any.h:112:48: error: call to deleted constructor of 'std::unique_ptr<int *, std::default_delete<int *> >'
    template<typename U> Derived(U&& value_) : value(std::forward<U>(value_)) {
                                               ^     ~~~~~~~~~~~~~~~~~~~~~~~
antlr4-cpp-runtime-prefix/include/antlr4-runtime/support/Any.h:118:18: note: in instantiation of function template specialization 'antlrcpp::Any::Derived<std::unique_ptr<int *, std::default_delete<int *> > >::Derived<const std::unique_ptr<int *, std::default_delete<int *> > &>' requested here
      return new Derived<T>(value);
                 ^
antlr4-cpp-runtime-prefix/include/antlr4-runtime/support/Any.h:112:26: note: in instantiation of member function 'antlrcpp::Any::Derived<std::unique_ptr<int *, std::default_delete<int *> > >::clone' requested here
    template<typename U> Derived(U&& value_) : value(std::forward<U>(value_)) {
                         ^
antlr4-cpp-runtime-prefix/include/antlr4-runtime/support/Any.h:44:29: note: in instantiation of function template specialization 'antlrcpp::Any::Derived<std::unique_ptr<int *, std::default_delete<int *> > >::Derived<std::unique_ptr<int *, std::default_delete<int *> > >' requested here
  Any(U&& value) : _ptr(new Derived<StorageType<U>>(std::forward<U>(value))) {
                            ^
testje.cpp:7:17: note: in instantiation of function template specialization 'antlrcpp::Any::Any<std::unique_ptr<int *, std::default_delete<int *> > >' requested here
  antlrcpp::Any b(std::move(a));
                ^
/usr/lib/gcc/x86_64-pc-linux-gnu/5.4.0/include/g++-v5/bits/unique_ptr.h:359:7: note: 'unique_ptr' has been explicitly marked deleted here
      unique_ptr(const unique_ptr&) = delete;
      ^
1 error generated.

I'm not sure where the clone method is actually used, but from looking at the name I would say it makes sense that it would do a copy.
Any idea how to fix this? I'm using Antlr 4.7.

Regards,
Maurice.

Mike Lischke

unread,
May 2, 2017, 3:36:35 AM5/2/17
to antlr-di...@googlegroups.com
Hi Maurice,

I'm making a visitor that constructs the object model for my application after parsing something from file.
This object model includes unique_ptrs to hold ownership for some objects. When returning these from visitor methods, I get compilation errors having to do with unique_ptrs being put in the Any class.
(FYI: I only recently learned about unique_ptr and move semantics).

I'm not sure you can do that. std::unique_ptr is not copyable (it would defeat its purpose if it were) and hence can only be used as single instance for a pointer or you have to move ownership. The Any class is not made for that. As you can see in the error, it wants to call the copy constructor of std::unique_ptr which is explicitly deleted.

However, data in a visitor is short-lived anyway, so it would not be a problem to just pass raw pointers around and manage their lifetime outside of the visit calls (e.g. in the visitor). It's not mandatory to you use the return values in the visit methods. You could instead also use a member in your visitor class and update that as you are visiting the parse tree.

Maurice van der Pot

unread,
May 3, 2017, 3:29:42 PM5/3/17
to antlr-discussion
Hi Mike,

Thanks for the quick response.

Instead of putting objects into member variables of the visitor, I've tried a different modification instead.
I could not think of a reason that there would need to be a copy constructor of the Any class for the purposes of a visitor, so I went ahead and removed them along with the clone functions to see what needed them.
It turns out in my case the only use of a copy constructor is in the aggregateResult function.

If I rewrite that to the following then I do not need any copy constructor and it becomes possible to store unique_ptrs in Any:

    virtual antlrcpp::Any aggregateResult(antlrcpp::Any &/*aggregate*/, antlrcpp::Any &nextResult) {
      return std::move(nextResult);
    }

Can you think of any reason why one would ever want to copy an Any (in the context of visitors)?

Regards,
Maurice.

Mike Lischke

unread,
May 4, 2017, 2:58:13 AM5/4/17
to antlr-di...@googlegroups.com

If I rewrite that to the following then I do not need any copy constructor and it becomes possible to store unique_ptrs in Any:

    virtual antlrcpp::Any aggregateResult(antlrcpp::Any &/*aggregate*/, antlrcpp::Any &nextResult) {
      return std::move(nextResult);
    }

Can you think of any reason why one would ever want to copy an Any (in the context of visitors)?

Hard to say, depends of course on your code. There's no problem in copying an Any instance. It's just tricky with a std::unique_ptr, because that is a very special class.

Maurice van der Pot

unread,
May 4, 2017, 4:47:24 PM5/4/17
to antlr-di...@googlegroups.com
That's what I meant. If there is no need to copy an Any instance, then it can be made to support unique_ptrs.

The whole purpose of Any in visitors in my mind is to pass ownership of an arbitrary object created in one function up to its caller.
Unique_ptr was created to support this transfer of ownership, so it is unfortunate that the copy constructors are blocking its use.

I'll submit it as a request on github.

Regards,
Maurice.


--
You received this message because you are subscribed to a topic in the Google Groups "antlr-discussion" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/antlr-discussion/-LxbnbPTSzA/unsubscribe.
To unsubscribe from this group and all its topics, send an email to antlr-discussion+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Mike Lischke

unread,
May 5, 2017, 2:55:28 AM5/5/17
to antlr-di...@googlegroups.com

> That's what I meant. If there is no need to copy an Any instance, then it can be made to support unique_ptrs.
>
> The whole purpose of Any in visitors in my mind is to pass ownership of an arbitrary object created in one function up to its caller.
> Unique_ptr was created to support this transfer of ownership, so it is unfortunate that the copy constructors are blocking its use.


But you can't foresee what others do with that class. Just because it gets in **your** way doesn't mean its behavior is wrong. The Any class exists for maximum flexibility without having to deal with templates. In C++ you cannot use virtual template functions (which is quite common with Java generics) hence a different approach was needed, which also shows in other places (e.g. Recognizer is not templated in C++).

Mike
--
www.soft-gems.net

Reply all
Reply to author
Forward
0 new messages