Boost logo

Boost :

Subject: Re: [boost] [yap] Review part 2: implementation
From: Zach Laine (whatwasthataddress_at_[hidden])
Date: 2018-02-15 20:51:08


On Thu, Feb 15, 2018 at 10:11 AM, Steven Watanabe via Boost <
boost_at_[hidden]> wrote:

> AMDG
>
> On 02/14/2018 10:29 PM, Zach Laine via Boost wrote:
> > On Wed, Feb 14, 2018 at 4:45 PM, Steven Watanabe via Boost <
> > boost_at_[hidden]> wrote:
> >
> >> On 02/14/2018 03:11 PM, Zach Laine via Boost wrote:
> >>> On Tue, Feb 13, 2018 at 4:51 PM, Steven Watanabe via Boost <
> >>> boost_at_[hidden]> wrote:
> >>>
> >>>> algorithm.hpp:
> >>>>
> >>>> 221: template <long long I, typename Expr>
> >>>> decltype(auto) get (Expr && expr, hana::llong<I> i);
> >>>> Does this need to be restricted to hana::llong, rather
> >>>> than, say, std::integral_constant?
> >>>>
> >>>
> >>> It's the lack of nice syntax for integral_constant literals that made
> me
> >>> choose this. I write get(expr, N_c) a lot, and I expect users to as
> >> well.
> >>>
> >>
> >> Supporting an IntegralConstant doesn't mean that
> >> you can't pass 0_c.
> >
> >
> > Is the change from std::integral_constant to IntegralConstant
> significant?
> > That is, are you asking that I accept models of some concept, or just
> > std::integral_constant?
> >
>
> I meant hana::IntegralConstant in the first place.
> std::integral_constant was just an example of another
> IntegralConstant, which hana::at can accept.

Great. Will do then.

> >
> >>> <snip>
> >>>> expression_free_operators.hpp/expression_if_else.hpp:
> >>>>
> >>>> - Why is this not part of expression.hpp?
> >>>>
> >>>
> >>> For the same reason that expression_free_operators.hpp is not. Those
> >> three
> >>> headers are separate pieces that you may want some or all of, so I kept
> >>> them separate.
> >>>
> >>
> >> expression_if_else makes a certain amount of sense as
> >> being separate. Making expression_free_operators separate
> >> comes with a high risk of ODR problems in any code that
> >> has different behavior depending on whether a given operator
> >> is defined. It's extra strange because expression_free_operators.hpp
> >> only has half the operator overloads, with the other half
> >> being defined as members.
> >
> >
> > I've read this a few times and don't get it. Without including
> > expression_free_operators.hpp, where might the other ODR-colliding
> > operators come from? Do you mean if the user defines her own operators
> for
> > expression<>, and then includes expression_free_operators.hpp in another
> > TU, or something else?
> >
>
> I was talking about the one definition rule as applied
> to some function that uses the operators.
> As an example, consider something that you yourself
> have written:
>
> boost/yap/print.hpp:
>
> template <typename T, typename = void_t<>>
> struct printer
> {
> std::ostream & operator() (std::ostream & os, T const &)
> { return os << "<<unprintable-value>>"; }
> };
>
> template <typename T>
> struct printer<
> T,
> void_t<decltype(
> std::declval<std::ostream &>() << std::declval<T const &>()
> )> >
> {
> std::ostream & operator() (std::ostream & os, T const & x)
> { return os << x; }
> };
>
> Now consider a class that defines a stream operator separately
> from the class:
>
> // x.hpp
> class X {};
>
> // x_print.hpp
> std::ostream& operator<<(std::ostream&, const X&);
>
> Next, I have two separate translation units:
>
> //a.cpp
> #include <x.hpp>
> #include <x_print.hpp>
> yap::detail::print_value(cout, X{});
>
> // b.cpp
> #include <x.hpp>
> yap::detail::print_value(cout, X{});
>
> printer chooses a different specialization in a.cpp
> than it does in b.cpp, which results in undefined
> behavior.
>
> As a result of this problem, I believe that any
> free functions (including operators) that are intended
> to be found by ADL *must* be declared alongside the
> class definition.

Ah, thanks. I'll probably just jam everything into expression.hpp then.

Zach


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk