[cfe-dev] RFC: Help rewriting <valarray> to support types derived from std::valarray.

Eric Fiselier via cfe-dev cfe-dev at lists.llvm.org
Wed Sep 30 23:14:37 PDT 2015


Hi All,

I'm looking for advice, help and optimally a volunteer to help fix a
substantial libc++ bug.

Currently the bug described below prevents libc++ from being used with
the SPEC v6 benchmarks and the SPEC developers have reached
out and requested a fix.

Unfortunately the required change is VERY large and I won't have time
to do it myself. However I am very willing to work closely with
anybody who would be willing to author a patch.


==========
The Problem
==========

Currently <valarray> has a large problem that prevents it from
supporting types derived from std::valarray<T>. Currently the
arithmetic operators in <valarray> are defined as follows:

template <class Tp, class Up,
               class = EnableIfValarrayOrExpressionTemplate<Tp>::type,
               class = EnableIfValarrayOrExpressionTemplate<Up>::type>
RET operator OP (Tp const&, Up const&);

We can make "EnableIfValarrayOrExpressionTemplate" detect and support types
that derive from std::valarray but this doesn't solve the problem. The
real issue with this
design is that the template parameter "Tp" is an exact match for
whatever type is passed in.
Because "Tp" is always an exact match it can cause the operator to be
ambiguous in cases where it should not be.

In the following example any attempt to call "operator+" with
"IntValarray" types will cause a compilation failure because both the
user and standard lib operators match and neither is more specialized.

struct IntValarray : std::valarray<int> {};
inline RET operator OP (IntValarray const&, IntValarray const&);

If libc++ correctly defined the functions to take a "std::valarray<T>"
there would be no ambiguity because the standard lib version of
operator function would require a conversion from IntArray ->
valarray<int> and so the user provided operator would be a better
match.

======
The Fix
======

In order to fully fix this problem <valarray> will need to be entirely
rewritten. Every operator or function that takes a valarray would have
to be rewritten as two or more separate overloads including one that
takes a std::valarray and another that takes the internal expression
template types.

The original overload definition given above would have the original
operator function definition would have to be redefined as four
separate overloads.

template <class Tp, class Up>
RET operator OP (std::valarray<Tp> const&, std::valarray<Up> const&);

template <class Tp, class Up,
               class = EnableIfExpressionTemplate<Up>::type>
RET operator OP (std::valarray<Tp> const&, Up const&);

template <class Tp, class Up,
               class = EnableIfExpressionTemplate<Tp>::type>
RET operator OP (Tp const&, std::valarray<Up> const&);

template <class Tp, class Up,
               class = EnableIfExpressionTemplate<Tp>::type,
               class = EnableIfExpressionTemplate<Up>::type>
RET operator OP (Tp const&, Up const&);


This would effectively double the size of the header, which is
currently 4000 lines long. The fix would also require substantial
testing. The current  tests provide poor coverage of valarray and much
of the burden of improving the tests would fall on the author of this
patch.

I welcome any feedback you have. Hopefully I'm wrong and there is a
simpler way to fix this.

Thanks for your time.

/Eric



More information about the cfe-dev mailing list