使用空初始值设定项作为参数的 C++11 代码在 GCC 4.8、7、Cygwin 中编译,但在 MSVC 2017 中不编译

C++11 code using empty initalizer as parmeter compiles in GCC 4.8, 7, Cygwin, but not MSVS 2017

根据要求,我有一个代码文件可以在 cygwin 上编译和运行,但不能在 MSVS 中使用空初始化器作为模板函数的参数在 gcc 中是可以的,但在 MSVS 中不行:

    // TestError.cpp : Defines the entry point for the console application.
//


#include <iostream>
#include <array>
#include <vector>

template <typename T>
class otherclass
{
public:
    T* allocated;
    otherclass(int n) { allocated = new T[n]; }
    ~otherclass() { delete[] allocated; }
};

class otherclass_accessor
{
public:
    int sz;
    otherclass_accessor(int inputSize) : sz(inputSize) {}
};

template<typename T>
class baseclass : public otherclass_accessor
{
private:
    std::vector<T*> mPointers;
public:
    T const * const * sp;
    std::vector<T> someVector;
    baseclass(std::vector<T>& someVector) : otherclass_accessor(someVector) {}
    ~baseclass() { mPointers.resize(0); }
};

class RRC : public baseclass<int>
{ 
public:
    template <typename T> RRC(otherclass<T>& a) : baseclass<void>(reinterpret_cast<otherclass<void>&>(a)) {}
    template< typename T > operator baseclass<T> const & () const { return reinterpret_cast< baseclass<T> const & >(*this); }
};

template< int N > using ARRC = std::array<RRC, N>;

template <int A>
void run_filter_multi(ARRC<A> in)
{
    std::cout << "Input Size:" << in.size() << std::endl;
}
int main()
{
    run_filter_multi<0>({});
    return 0;
}

使用 g++ -std=c++11 TestError.cpp -o test 编译 和输出: 输入Size:0

但使用 MSVS2017 时出现错误 C2664:

1>------ 构建开始:项目:TestError,配置:调试 Win32 ------ 1>TestError.cpp 1>c:\users\dayd\documents\visual studio 2017\projects\testerror\testerror.cpp(53): error C2664: 'void run_filter_multi<0>(std::array)': 无法将参数 1 从 'initializer list' 转换为 'std::array' 1>c:\users\dayd\documents\visual studio 2017\projects\testerror\testerror.cpp(53): 注意:聚合初始化无效 1> 完成构建项目 "TestError.vcxproj" -- 失败。 ========== 构建:0 成功,1 失败,0 最新,0 跳过 ==========

所以 - 现在我的问题是,为什么空初始化器可以用于 g++,但不能用于 MSVS2017?这是一个淡化版本,我试图模拟我在一个更大的项目中所经历的事情,我正在尝试制作 "cross platform"。我似乎想不出在 MSVS 中绕过它的方法。我曾尝试使用 std::vector 而不是 std::array,但是 std::array 在我继承的代码中非常普遍,以至于尝试更改所有底层将是非常痛苦的,充其量也是如此。

谢谢!

有一些问题,但最引人注目的是:

#include <array>
struct S { S(int); }; // Not default-constructible.
std::array<S, 0> x {};

这失败了

error C2073: 'std::array<S,0>::_Elems': elements of partially initialized array must have a default constructor

由于 C++ 不允许零长度数组,但 std::array<T, 0> 仍然可以工作,因此必须使用一些小技巧来实现。不幸的是,MSVC 的诡计被打破了:它给它一个 T[1] 类型的字段,然后由于无法构造空的未使用 T 元素而严重失败。

我看到的解决这个问题的唯一方法是给 RRC 一个默认构造函数,或者避免 std::array<T, 0>.