简体   繁体   English

是否可以就地构造固定大小的数组作为函数参数?

[英]Is it possible to construct a fixed sized array in-place as a function argument?

This is mainly a question about a corner of C++ syntax related to fixed-sized arrays. 这主要是关于与固定大小的数组有关的C ++语法的一个问题。

Suppose I have a function that exploits type information, for example: 假设我有一个利用类型信息的函数,例如:

template<class T> void fun(T const& t){
    std::cout << typeid(t).name() << std::endl;
}

I can pass a value or a temporary object: 我可以传递一个值或一个临时对象:

int i;
fun(i); // prints "int" ("i" actually)
fun(int{});   // prints "int" ("i" actually)

However I can't do the same with arrays 但是我不能对数组做同样的事情

double a[10][10];
fun(a); // ok, prints "a[10][10]" ("A10_A10_d" actually)

fun(double[10][10]); // doesn't compile
fun(double{}[10][10]); // doesn't compile
fun(double[10][10]{}); // doesn't compile
fun(double()[10][10]); // doesn't compile
fun(double[10][10]()); // doesn't compile
fun(double(&)[10][10]); // doesn't compile
fun(double(*)[10][10]); // doesn't compile

I could in principle do: 我原则上可以做到:

typedef double a1010[10][10];
fun(a1010{});

but, is it possible to do without predefining a typedef? 但是, 可以不预先定义typedef而做吗?

Is it possible at all to construct a fixed sized array in-place as a function argument? 是否可以就地构造固定大小的数组作为函数参数?

Full code: 完整代码:

template<class T> void fun(T const& t){
    std::cout << typeid(t).name() << std::endl;
}

typedef double a1010[10][10];

int main(){
    int i;
    fun(i); // prints "int" ("i" actually)
    double a[10][10];
    fun(a); // prints "a[10][10]" ("A10_A10_d" actually)
    fun(a1010{});

    fun(int{});   // prints "int"
/*  fun(double[10][10]); // doesn't compile
    fun(double{}[10][10]); // doesn't compile
    fun(double[10][10]{}); // doesn't compile
    fun(double()[10][10]); // doesn't compile
    fun(double[10][10]()); // doesn't compile
    fun(double(&)[10][10]); // doesn't compile
    fun(double(*)[10][10]); // doesn't compile
    */
    return 0;
}

Bonus points (probably a bounty): What about variable-sized arrays? 奖励点(可能是赏金):可变大小的数组呢?

int N = 10;
f(double[N]);

Try: 尝试:

fun((int[3]){1,2,3});
fun((int[5]){});

As for the "bonus points": variable sized arrays are not part of the language. 至于“加分点”:可变大小的数组不是该语言的一部分。 This extension to the language does not work with template arguments: 此语言的扩展不适用于模板参数:

prog.cc:4:6: note: candidate template ignored: substitution failure : variably modified type 'int [n]' cannot be used as a template argument fun(const T&t) prog.cc:4:6:注意:候选模板被忽略:替换失败:可变修改类型'int [n]'不能用作模板参数fun(const T&t)

Edit 编辑

As Chris noted, the above solution proposes to use compound literals , which are an extension to C++. 克里斯指出,上述解决方案建议使用复合文字 ,这是对C ++的扩展。 There is a solution that avoids this extension to C++, using a simple helper class: 有一个解决方案,可以使用一个简单的帮助程序类来避免将此扩展到C ++:

template <class T, std::size_t N>
struct my_array
{
    T data[N];
};

template <class T, std::size_t N>
void print(const T (&x)[N])
{
     for (auto i: x)
         std::cout << i << '\n';
}

int main()
{
    print(my_array<int,3>{9,10,11}.data);
}

This works well, but requires one to add template argument to my_array, which are not deduced. 这很好用,但是需要一个将模板参数添加到my_array的方法,而不能推导。 With C++17 it is possible to automatically deduce type and size: 使用C ++ 17可以自动推断类型和大小:

template <class T, std::size_t N>
struct my_array
{
    constexpr my_array(std::initializer_list<T> x)
    {
       std::size_t i = 0;
       for (auto val : x)
           data[i++] = val;
    }
    T data[N];
};
template <class ...T>
my_array(T...) -> my_array<typename std::common_type<T...>::type, sizeof...(T)>;

int main()
{
    print(my_array{9,10,11}.data);
}

For two dimensional arrays this is slightly more complicated: 对于二维数组,这稍微复杂一些:

template <class T, std::size_t N1, std::size_t N2>
struct my_array2d
{
    constexpr my_array2d(std::initializer_list<std::initializer_list<T> > x)
    {
        std::size_t i = 0;
        for (const auto & row : x) {
            int j=0;
            for (const auto & val: row) {
                data[i][j++] = val;
            }
            i++;
        }
    }
    T data[N1][N2];
};
int main()
{
    work(my_array2d<int, 3, 2>{{9,1},{10,2},{11,3}}.data);
}

I have given up on deduction guides for two dimensional arrays, but I believe they are possible. 我已经放弃了二维数组的推导指南,但是我相信它们是可能的。

You have tried many combinations with double , but you seem to have missed out on one. 您尝试过使用double多种组合,但是您似乎错过了其中一种。

fun((double[10][10]){});

This compiles and gives: A10_A10_d 编译并给出: A10_A10_d

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM