代码之家  ›  专栏  ›  技术社区  ›  alfC

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

  •  2
  • alfC  · 技术社区  · 6 年前

    这主要是关于C++语法与固定大小数组有关的一个问题。

    假设我有一个利用类型信息的函数,例如:

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

    我可以传递值或临时对象:

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

    但是,我不能对数组执行相同的操作

    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
    

    原则上我可以:

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

    有没有可能在原地构造一个固定大小的数组作为函数参数?

    完整代码:

    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;
    }
    

    int N = 10;
    f(double[N]);
    
    2 回复  |  直到 6 年前
        1
  •  5
  •   Michael Veksler    6 年前

    尝试:

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

    至于“加分”:可变大小的数组不是语言的一部分。此语言扩展不适用于模板参数:

    prog.cc:4:6:注意:已忽略候选模板:替换失败: 可变修改类型“int[n]”不能用作模板参数

    编辑

    正如Chris所指出的,上面的解决方案建议使用 复合文字 ,这是对C++的扩展。有一个解决方案,避免了使用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);
    }
    

    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);
    }
    

    对于二维数组,这稍微复杂一些:

    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);
    }
    

        2
  •  1
  •   P.W    6 年前

    double 但你好像错过了一个。

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

    A10_A10_d