gpt4 book ai didi

c++ - ctor 在 clang 和 gcc 上的单个和多个 std::initializer_list ctors 之间是不明确的,但不是 msvc

转载 作者:行者123 更新时间:2023-12-05 02:26:55 26 4
gpt4 key购买 nike

我有一个用于创建二维矩阵的嵌套 initializer_list 构造器。效果很好。但后来我决定使用单个初始化列表添加一个简化的行 vector 矩阵(n 行,1 列)。这样我就可以创建一个这样的行矩阵:Matrix2D<int> x{1,2,3}而不是必须这样做:Matrix2D<int> x{{1},{2},{3}} .当然,这需要一个单独的 ctor。

一切正常,包括在 MSVC 的 constexpr 中。但是当使用 gcc 和 clang 检查时,我得到了不明确的 ctors。当列表是嵌套的并且 MSVC 完全按预期运行时,对我来说似乎很清楚。

代码如下:

// Comment out next line for only nested initializer_list ctor
#define INCLUDE_EXTRA_CTOR
#include <memory>
#include <numeric>
#include <initializer_list>
#include <exception>
#include <stdexcept>
#include <concepts>

using std::size_t;
template <typename T>
class Matrix2D {
T* const pv; // pointer to matrix contents
public:
const size_t cols;
const size_t rows;

// default ctor;
Matrix2D() noexcept : pv(nullptr), cols(0), rows(0) {}

// 2D List initialized ctor
Matrix2D(std::initializer_list<std::initializer_list<T>> list) :
pv((list.begin())->size() != 0 ? new T[list.size() * (list.begin())->size()] : nullptr),
cols(pv != nullptr ? (list.begin())->size() : 0),
rows(pv != nullptr ? list.size() : 0)
{
if (pv == nullptr)
return;
for (size_t row = 0; row < list.size(); row++)
{
if (cols != (list.begin() + row)->size())
throw std::runtime_error("number of columns in each row must be the same");
for (size_t col = 0; col < cols; col++)
pv[cols * row + col] = *((list.begin() + row)->begin() + col);
}
}
#ifdef INCLUDE_EXTRA_CTOR
// Row initialized ctor, rows=n, cols=1;
Matrix2D(std::initializer_list<T> list) :
pv(list.size() != 0 ? new T[list.size()] : nullptr),
cols(pv != nullptr ? 1 : 0),
rows(pv != nullptr ? list.size() : 0)
{
if (pv == nullptr)
return;
for (size_t row = 0; row < rows; row++)
{
pv[row] = *(list.begin() + row);
}
}
#endif

// dtor
~Matrix2D() { delete[] pv; }
};

int main()
{
// Tests of various possible null declarations
Matrix2D<int> x1{ }; // default
Matrix2D<int> x2{ {} }; // E0309, nested init list with 1 row, 0 cols, forced to 0 rows, 0 cols
Matrix2D<int> x3{ {},{} }; // E0309, nested init list with 2 rows, 0 cols, forced to 0 rows, 0 cols

// typical declaration
Matrix2D<int> x4{ {1,2},{3,4},{5,6} }; // nested init list with 3 rows, 2 cols
// standard row vector declaration
Matrix2D<int> x5{ {1},{2},{3} }; // E0309, init list with 3 rows, 1 col

#ifdef INCLUDE_EXTRA_CTOR
// row vector declaration
Matrix2D<int> x6{ 1,2,3 }; // init list with 3 rows, 1 col
#endif
}

E0309 是 MSVC 智能感知不明确构造函数错误。但是,编译没有错误为什么 gcc 和 clang 推导不明确?有解决方法吗?

Compiler Explorer

最佳答案

However, compiles w/o error Why are gcc and clang deductionsambiguous?

这里出现歧义是因为{}{1}也可以初始化单个 int .

Is there a workaround?

模板化你的专用构造函数使得 {}永远不会被推断为 initializer_list这仍然适用于 {1,2,3} .

#ifdef INCLUDE_EXTRA_CTOR
// Row initialized ctor, rows=n, cols=1;
template<class U>
Matrix2D(std::initializer_list<U> list) :
pv(list.size() != 0 ? new T[list.size()] : nullptr),
cols(pv != nullptr ? 1 : 0),
rows(pv != nullptr ? list.size() : 0)
{
fmt::print("1: {}\n", list);
if (pv == nullptr)
return;
for (size_t row = 0; row < rows; row++)
{
pv[row] = *(list.begin() + row);
}
}
#endif

如果你想要Matrix2D<double> d1{ 1,2,4. }工作,那么你可以使用 type_identity_t在模板参数推导中建立非推导上下文:

// Row initialized ctor, rows=n, cols=1;
template<class U = T>
Matrix2D(std::initializer_list<std::type_identity_t<U>> list) :
pv(list.size() != 0 ? new T[list.size()] : nullptr),
cols(pv != nullptr ? 1 : 0),
rows(pv != nullptr ? list.size() : 0)
{

Demo

关于c++ - ctor 在 clang 和 gcc 上的单个和多个 std::initializer_list ctors 之间是不明确的,但不是 msvc,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73535031/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com