Modify

Ticket #7378 (closed Bugs: fixed)

Opened 19 months ago

Last modified 19 months ago

lookup_one_property fails if property tag not found

Reported by: Andreas Hehn <hehn@…> Owned by: dgregor
Milestone: To Be Determined Component: graph
Version: Boost 1.52.0 Severity: Problem
Keywords: lookup_one_property property_value Cc:

Description

boost::lookup_one_property<PropertyList,Tag>::found does not compile if Tag is not found in the PropertyList.

The problem originates from the lookup(...) function definition in the template specialization

  template <typename Tag, typename T, typename Base, typename PropName>
  struct lookup_one_property_internal<boost::property<Tag, T, Base>, PropName>: lookup_one_property_internal<Base, PropName> {
    private:
    typedef lookup_one_property_internal<Base, PropName> base_type;
    public:
    template <typename PL>
    static typename enable_if<is_same<PL, boost::property<Tag, T, Base> >, typename base_type::type&>::type
    lookup(PL& prop, const PropName& tag)

which requires the base class to provide a type member.

If the tag is not found the unspecialized template

    template <typename PList, typename PropName, typename Enable = void>
    struct lookup_one_property_internal {BOOST_STATIC_CONSTANT(bool, found = false);};

will be instantiated as Base where the compiler can't find any type member.

Attachments

example.cpp Download (369 bytes) - added by Andreas Hehn <hehn@…> 19 months ago.
demonstration code
property.hpp.patch Download (989 bytes) - added by Andreas Hehn <hehn@…> 19 months ago.
patch

Change History

Changed 19 months ago by Andreas Hehn <hehn@…>

demonstration code

comment:1 follow-up: ↓ 2 Changed 19 months ago by jewillco

  • Status changed from new to closed
  • Resolution set to wontfix
  • Component changed from property_map to graph

That change was made on purpose; it greatly helps error messages for using nonexistent property maps from graphs.

Changed 19 months ago by Andreas Hehn <hehn@…>

patch

comment:2 in reply to: ↑ 1 Changed 19 months ago by Andreas Hehn <hehn@…>

Replying to jewillco:

That change was made on purpose; it greatly helps error messages for using nonexistent property maps from graphs.

Is there another way of checking the existence of some particular property tag then?

comment:3 Changed 19 months ago by jewillco

Look at lookup_one_property<...>::found. That takes a property list and a tag and determines if the property is present in the list. That doesn't give an easy way to test a graph for a given property, though.

comment:4 Changed 19 months ago by anonymous

That's what I thought, but lookup_one_property<...>::found is not false if the tag is not found, instead it just results in a compiler error.

comment:5 Changed 19 months ago by jewillco

What triggers the error in that case?

comment:6 Changed 19 months ago by Andreas Hehn <hehn@…>

That's what I reported in this bug report. Or am I missing something?

comment:7 Changed 19 months ago by Andreas Hehn <hehn@…>

The problem is that in the enable_if of the lookup(...) member function

template <typename Tag, typename T, typename Base, typename PropName>
  struct lookup_one_property_internal<boost::property<Tag, T, Base>, PropName>: lookup_one_property_internal<Base, PropName> {
    private:
    typedef lookup_one_property_internal<Base, PropName> base_type;
    public:
    template <typename PL>
    static typename enable_if<is_same<PL, boost::property<Tag, T, Base> >, typename base_type::type&>::type
    lookup(PL& prop, const PropName& tag)

typename base_type::type& does not depend on the template parameter of the template member function but only on the template parameters of the class. Therefore base_type::type is required to exist, even if lookup(...) is not used (or the enable_if<...> disables the function).

A solution could be to add a indirection which depeneds on PL, like

 template <class First, class Second>
 struct second_type {
     typedef Second type;
 };

...

    static typename enable_if<is_same<PL, boost::property<Tag, T, Base> >, typename second_type<PL,base_type>::type::type&>::type
    lookup(PL& prop, const PropName& tag)

which will prevent the compiler from resolving base_type::type unless lookup(...) is explicitly instantiated.

This way the general template lookup_one_property_internal does not need to define a type member to use lookup_one_property<...>::found.

But I have to admit that this solution looks a little ugly.

comment:8 Changed 19 months ago by jewillco

(In [80524]) Added void as default value of lookup_one_property_internal::type for "not found"; refs #7378

comment:9 Changed 19 months ago by Andreas Hehn <hehn@…>

  • Status changed from closed to reopened
  • Resolution wontfix deleted

This was also my first approach, but unfortunately it doesn't solve the problem.

Since the return type of lookup(...) is type& the compiler will complain if type is void, as you can see if you try to compile my example code.

comment:10 Changed 19 months ago by jewillco

  • Status changed from reopened to closed
  • Resolution set to fixed

(In [80528]) Using lazy_enable_if to avoid "reference to void" errors for properties that are not found; fixes #7378

comment:11 Changed 19 months ago by Andreas Hehn <hehn@…>

Great! That solved the problem. I totally forgot about lazy_enable_if...

Could you also apply the same fix to struct lookup_one_property<const T, Tag> in line 159 of the same file?

Thanks for fixing the problem so quickly! :)

comment:12 Changed 19 months ago by jewillco

(In [80532]) Further fixed #7378 issue; refs #7378

View

Add a comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
The resolution will be deleted. Next status will be 'reopened'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.