2015-12-01 21 views
10

Tôi muốn chuyển đổi một số std::array sang một số khác std::array, nhân mỗi phần tử của nó với một số cụ thể.Nhân mỗi phần tử của mảng std :: tại thời gian biên dịch

Những gì tôi đã ngay bây giờ rõ ràng là không hoạt động:

#include <array> 
#include <iostream> 
#include <utility> 

template <class T, size_t... Is, size_t N> 
constexpr std::array<T, N> multiply(std::array<T, N> const &src, 
            std::index_sequence<Is...>) { 
    return std::array<T, N>{{src[Is]...}}; // How can I multiply each of src's elements? 
} 

int main(int argc, char *argv[]) { 
    constexpr std::array<int, 3> arr = {1, 2, 3}; 
    constexpr auto t = multiply(arr, std::make_index_sequence<3>{}); 
    for (auto &el : t) std::cout << el << std::endl; 
    return 0; 
} 

Câu hỏi của tôi là: làm thế nào tôi có thể lặp qua mỗi phần tử tại thời gian biên dịch hoặc làm thế nào tôi có thể áp dụng các chức năng tương tự (trong trường hợp của tôi: nhân 2) tại thời gian biên dịch?

Trả lời

14

Bạn có thể làm điều đó theo cách sau:

template<typename T> 
constexpr T mult(T const &a, T const &b) { return a * b; } 

template <class T, size_t... Is, size_t N> 
constexpr std::array<T, N> multiply(std::array<T, N> const &src, 
            std::index_sequence<Is...>) { 
    return std::array<T, N>{{mult(src[Is], src[Is])...}}; 
} 

Live Demo

Hoặc nếu bạn muốn nhân với một số bạn có thể thay đổi để:

template<typename T> 
constexpr T mult(T const &a, T const &b) { return a * b; } 

template <class T, size_t... Is, size_t N> 
constexpr std::array<T, N> multiply(std::array<T, N> const &src, 
            std::index_sequence<Is...>, T const &mul) { 
    return std::array<T, N>{{mult(src[Is], mul)...}}; 
} 

Live Demo

Như được giải thích trong cppreference:Một mẫu được theo sau bởi dấu ba chấm, trong đó tên của ít nhất một gói tham số xuất hiện ít nhất một lần, được mở rộng thành 0 hoặc nhiều dấu phân tách bằng dấu phẩy của mẫu, trong đó tên của gói tham số được thay thế bằng mỗi loại trong gói, theo thứ tự. Gói mở rộng chỉ có thể xảy ra trong bối cảnh mở rộng gói. Những yếu là:

  • chuẩn bị tinh thần khởi
  • danh sách initializer
  • khởi tạo tổng hợp
  • chức năng gọi
  • khởi tạo mảng

Edit:

Như T.C. chỉ trong các ý kiến ​​bạn cũng có thể làm điều đó đơn giản như:

template <class T, size_t... Is, size_t N> 
constexpr std::array<T, N> multiply(std::array<T, N> const &src, std::index_sequence<Is...>, T const &mul) { 
    return std::array<T, N>{{(src[Is] * mul)...}}; 
} 

Live Demo

+0

như thế nào '{{mult (src [là], src [là]) ...} 'làm việc bán chính xác ? '...' là một chút bối rối trong trường hợp này. – syntagma

+0

@REACHUS Đây là một trong những cách bạn có thể mở rộng gói. Chờ tôi sẽ cố gắng giải thích. – 101010

+0

Cảm ơn, một câu hỏi nữa: liệu có cách nào để thay thế 'mult' bằng lambda? Tôi đã thử nó nhưng có vẻ như nó sẽ không thể, vì lambdas không thể là 'constexpr'. – syntagma

Các vấn đề liên quan