Làm cách nào để làm cho structof sum của tôi hoạt động với gói tham số trống


8

Tôi có cấu trúc kiểu chữ này để xác định tổng kích thước của tất cả các loại được truyền vào:

template <typename U, typename... T> struct TotalSizeOf 
    : std::integral_constant<size_t, sizeof(U) + TotalSizeOf<T...>::value> {};

template <typename U> struct TotalSizeOf<U> 
    : std::integral_constant<size_t, sizeof(U)> {};

Sử dụng: TotalSizeOf<double, int, char>::value

Câu hỏi là, làm thế nào để tôi sửa đổi điều này để cho phép nó hoạt động trên gói tham số trống, để trả về 0;

ví dụ TotalSizeOf<>::value

Hiện tại, tôi nhận được lỗi error: wrong number of template arguments (0, should be at least 1)

Tôi chỉ có sẵn C ++ 14.


Bạn có thể định nghĩa một đối số mẫu mặc định và tạo một lớp sẽ trả về 0 cho sizeof không? nhưng tôi nghĩ thứ hai là không thể Có thể với một mảng trống như ở đây: stackoverflow.com/questions/47352663/ cấp
RoQuOTriX

Câu trả lời:


12

Bạn chỉ cần chuyên môn hóa cho <>

Thí dụ:

template < typename... T> struct TotalSizeOf;

template < typename U, typename... T> struct TotalSizeOf<U, T...>
: std::integral_constant<size_t, sizeof(U) + TotalSizeOf<T...>::value> {};

template <> struct TotalSizeOf<> :
std::integral_constant<size_t, 0 > { };

int main()
{
    std::cout << TotalSizeOf< int, char>::value << std::endl;
    std::cout << TotalSizeOf< char>::value << std::endl;
    std::cout << TotalSizeOf< >::value << std::endl;
}

Cảm ơn, tôi đã chuyên môn không chính xác vì tôi không có dòng trên cùng là phiên bản không chuyên biệt cơ bản như bạn.
Salgar

@Salgar: Khá thất bại phổ biến :-) Điều này dẫn đến "chuyên về số lượng đối số mẫu sai" ... BTW: Khi tôi viết ví dụ tôi cũng chạy vào đó :-)
Klaus

5

Với C ++ 17, bạn có thể có được điều này mà không cần lập trình siêu mẫu khuôn mẫu, sử dụng các biểu thức gấp:

#include <iostream>
#include <type_traits>

template<class... T> 
struct TotalSizeOf: std::integral_constant<std::size_t, (0 + ... + sizeof(T))> {};

int main()
{
    std::cout << TotalSizeOf< int, char>::value << std::endl;
    std::cout << TotalSizeOf< char>::value << std::endl;
    std::cout << TotalSizeOf< >::value << std::endl;
}

Điều này cũng sẽ hiệu quả hơn khi biên dịch (tất nhiên trong thời gian chạy, đây là như nhau).

PS: Chỉ cần đọc, rằng bạn chỉ có C ++ 14, nhưng sẽ để điều này đứng ở đây, vì tôi nghĩ thật tuyệt khi thấy rằng chúng ta ít bị buộc phải làm TMP khó xử trong các phiên bản C ++ mới hơn.

Phụ lục: Ít thanh lịch hơn C ++ 17, nhưng C ++ 14 và khá nhiều tmp-free

#include <iostream>
#include <type_traits>
#include <initializer_list>

constexpr size_t sum(std::initializer_list<size_t> arr) {
    // Accumulate is sadly not constexpr in C++14
    auto ret = 0ul;
    for(auto i: arr) {
        ret += i;
    }
    return ret;
}

template<class... T> 
struct TotalSizeOf: std::integral_constant<std::size_t, sum({sizeof(T)...})> {};

int main()
{
    std::cout << TotalSizeOf< int, char>::value << std::endl;
    std::cout << TotalSizeOf< char>::value << std::endl;
    std::cout << TotalSizeOf< >::value << std::endl;
}

1
Vâng, đó là gọn gàng. Tôi mong muốn có thể sử dụng các biểu thức gấp
Salgar
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.