https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107461

            Bug ID: 107461
           Summary: GCC rejects program with ambiguity error
           Product: gcc
           Version: 13.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: jlame646 at gmail dot com
  Target Milestone: ---

The following well-formed program(afaik) is rejected by gcc but accepted by
clang and msbc. Demo: https://godbolt.org/z/bMWxd8bEa

```
#include <iostream>
#include <type_traits>
#include <vector>
#include <string>
#include <functional>
#include <map>
#include <algorithm>
using namespace std;
#include <algorithm>
#include <array>
#include <type_traits>
#include <vector>

namespace MLL{
  template<typename data_t, std::size_t n_rows, std::size_t n_cols, std::size_t
MAX=256>
    class Matrix;    //this forward declaration not needed but you can have
this if you want and if you do then make sure that you only provide the default
arg 256 in declaration and not in definition
//--------------------------------------------------------------------------------vvvvvvv---->added
this default arg here instead of in forward declaration
    template<typename data_t, std::size_t n_rows, std::size_t n_cols,
std::size_t MAX>
    class Matrix{
        static constexpr bool IS_STATIC = n_rows * n_cols <= MAX;
        using container_t = typename std::conditional<IS_STATIC,
std::array<data_t, n_rows * n_cols>, std::vector<data_t>>::type;

        container_t m_data_list;

    public:
        Matrix(){
            if constexpr( !IS_STATIC ){
                m_data_list.resize(n_rows * n_cols);
            }
        }

        explicit Matrix(data_t default_value){
            if constexpr( IS_STATIC ){
                m_data_list.fill(default_value);
            }else{
                m_data_list.resize(n_rows * n_cols, default_value);
            }
        }

        explicit Matrix(std::initializer_list<data_t>&& value_list){
            std::copy(value_list.begin(), value_list.end(),
m_data_list.begin());
        }

        Matrix(Matrix const& other)
                : m_data_list(other.m_data_list){
        }

        Matrix(Matrix&& other) noexcept
                : m_data_list(std::move(other.m_data_list)){
        }

        Matrix& operator=(Matrix const& other){
            m_data_list = other.m_data_list;
            return *this;
        }

        Matrix& operator=(Matrix&& other) noexcept{
            m_data_list = std::move(other.m_data_list);
            return *this;
        }

        //renamed all the arguments by prefexing them with OP for better
readibility
        template<typename data_tOP, typename TOP, std::size_t n_rowst,
std::size_t n_colsOP, std::size_t MAXOP, std::size_t other_MAXOP>
    friend Matrix<decltype(std::declval<data_tOP>() + std::declval<TOP>()),
n_rowst, n_colsOP, std::min(MAXOP, other_MAXOP)>
    operator+(Matrix<data_tOP, n_rowst, n_colsOP, MAXOP> const& lhs,
Matrix<TOP, n_rowst, n_colsOP, other_MAXOP> const& rhs);
    };

     template<typename data_tOP, typename TOP, std::size_t n_rowst, std::size_t
n_colsOP, std::size_t MAXOP, std::size_t other_MAXOP>
    Matrix<decltype(std::declval<data_tOP>() + std::declval<TOP>()), n_rowst,
n_colsOP, std::min(MAXOP, other_MAXOP)>
    operator+(Matrix<data_tOP, n_rowst, n_colsOP, MAXOP> const& lhs,
Matrix<TOP, n_rowst, n_colsOP, other_MAXOP> const& rhs){
         const std::size_t n = n_rowst * n_colsOP;
        for( std::size_t i = 0; i < n; ++i ){
           // lhs.m_data_list[i] += rhs.m_data_list[i];   //can't assing using
const lvalue reference
        }
        return lhs;
    }
}
int main()
{

    MLL::Matrix<int, 4, 4> a({1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16});
    a+a;
    return 0;;
}

```

GCC rejects this with the error:

```
<source>:82:6: error: ambiguous overload for 'operator+' (operand types are
'MLL::Matrix<int, 4, 4>' and 'MLL::Matrix<int, 4, 4>')
   82 |     a+a;
      |     ~^~
      |     | |
      |     | Matrix<[...],[...],[...]>
      |     Matrix<[...],[...],[...]>
<source>:70:5: note: candidate: 'MLL::Matrix<decltype ((declval<data_tOP>() +
declval<TOP>())), n_rowst, n_colsOP, std::min<long unsigned int>(MAXOP,
other_MAXOP)> MLL::operator+(const Matrix<data_tOP, n_rowst, n_colsOP, MAXOP>&,
const Matrix<TOP, n_rowst, n_colsOP, other_MAXOP>&) [with data_tOP = int; TOP =
int; long unsigned int n_rowst = 4; long unsigned int n_colsOP = 4; long
unsigned int MAXOP = 256; long unsigned int other_MAXOP = 256; decltype
((declval<data_tOP>() + declval<TOP>())) = int]'
   70 |     operator+(Matrix<data_tOP, n_rowst, n_colsOP, MAXOP> const& lhs,
Matrix<TOP, n_rowst, n_colsOP, other_MAXOP> const& rhs){
      |     ^~~~~~~~
<source>:65:5: note: candidate: 'MLL::Matrix<decltype ((declval<data_tOP>() +
declval<TOP>())), n_rowst, n_colsOP, std::min<long unsigned int>(MAXOP,
other_MAXOP)> MLL::operator+(const Matrix<data_tOP, n_rowst, n_colsOP, MAXOP>&,
const Matrix<TOP, n_rowst, n_colsOP, other_MAXOP>&) [with data_tOP = int; TOP =
int; long unsigned int n_rowst = 4; long unsigned int n_colsOP = 4; long
unsigned int MAXOP = 256; long unsigned int other_MAXOP = 256; data_t = int;
long unsigned int n_rows = 4; long unsigned int n_cols = 4; long unsigned int
MAX = 256; decltype ((declval<data_tOP>() + declval<TOP>())) = int]'
   65 |     operator+(Matrix<data_tOP, n_rowst, n_colsOP, MAXOP> const& lhs,
Matrix<TOP, n_rowst, n_colsOP, other_MAXOP> const& rhs);
      |     ^~~~~~~~
```

Reply via email to