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); | ^~~~~~~~ ```