2016-08-03 16 views
6

tôi có chức năng như thế này:Làm thế nào để tạo ra chuỗi số nguyên tùy chỉnh trong C++

template <typename ... Types> 
void foo(const Types & ... values) 
{ 
    // expected that 'values' is sequence like 
    // '1, customvalue1, 2, customvalue2, 3,...' 
} 

Và chức năng thứ hai:

template <typename ... Types> 
void bar(const Types & ... values) 
{ 
    // where 'values' are any variables 
    // some magic here 
    foo((int_seq<sizeof...(Types)>, values)...); 
} 

Tôi muốn vượt qua bất kỳ chuỗi các biến để thanh, để trình tự này chuyển đổi thành chuỗi như '1, value1, 2, value2, 3, value3'. Vì vậy, mỗi giá trị theo sau số của nó trong chuỗi cơ sở. Nhưng tôi không thể tạo mã số ma thuật ' này để biến đổi chuỗi trên giai đoạn biên dịch giữa hai trạng thái này.

+2

Tôi giả định rằng 'bar' được cho là gọi' foo'? Không gọi chính nó một cách đệ quy? –

+0

bạn đã xem xét một mảng kết hợp chưa? Điều này có vẻ giống như một vấn đề đối với loại cấu trúc dữ liệu này –

+0

Có, tôi đã sai, dĩ nhiên là 'foo', không phải 'bar' –

Trả lời

1

Không thực sự thanh lịch nhưng, sử dụng các bộ, std::tie, vv ...

Ví dụ sau sẽ làm việc với C++ 11

--- EDIT ---

Modified và hợp nhất (C++ 11 không có phần tử C++ 14) ví dụ đầu tiên của tôi.

Không cần của std::index_sequence (một tầm thường struct indSeq có thể được sử dụng thay) hoặc std::make_index_sequence (chuỗi chỉ số có thể được contructed từng bước sử dụng sizeof...(I)); không cần qux() nữa.

#include <tuple> 
#include <iostream> 


void foo() 
{ } 

template <typename T0, typename ... Types> 
void foo (const T0 & v0, const Types & ... values) 
{ 
    std::cout << "-- " << v0 << std::endl; 

    foo(values...); 
} 


template <std::size_t ...> 
struct indSeq 
{ }; 

template <std::size_t ... Is, typename ... Ts1> 
void baz (std::size_t, const indSeq<Is...> &, const std::tuple<Ts1...> & t) 
{ foo(std::get<Is>(t)...); } 

template <std::size_t ... Is, typename ... Ts1, typename T0, typename ... Ts2> 
void baz (std::size_t n, const indSeq<Is...> &, const std::tuple<Ts1...> & t, 
      const T0 & v0, const Ts2 & ... vs) 
{ baz(n+1U, indSeq<Is..., sizeof...(Is), sizeof...(Is)+1U>(), 
     std::tuple_cat(t, std::tie(n), std::tie(v0)), vs...); } 

template <typename ... Types> 
void bar (const Types & ... values) 
{ baz (1U, indSeq<>(), std::tuple<>(), values...); } 

int main() 
{ 
    bar(11, 22L, "33", 44.44); 
    return 0; 
} 

p.s .: xin lỗi vì tiếng Anh xấu của tôi.

2

Đây là giải pháp C++ 14, nhưng tất cả các phần thư viện cần thiết cũng có thể được viết bằng C++ 11.

#include <iostream> 
#include <tuple> 
#include <utility> 

template <typename ... Types> 
void foo(const Types & ... values) 
{ 
    using swallow = bool[]; 
    (void)swallow{ (std::cout << values << std::endl,false)... }; 
} 

template <std::size_t N, bool = (N%2==0)> 
struct pick { 
    template<typename... Types> 
    static std::size_t get(const std::tuple<Types...>&) { return N/2; } 
}; 

template <std::size_t N> 
struct pick<N,false> { 
    template<typename... Types> 
    static auto get(const std::tuple<Types...>& t) { return std::get<N/2>(t); } 
}; 

template <std::size_t... Indices, typename ... Types> 
void bar2(const std::index_sequence<Indices...>, const Types & ... values) 
{ 
    auto x = std::tie(values...); 
    foo(pick<Indices>::get(x)...); 
} 

template <typename ... Types> 
void bar(const Types & ... values) 
{ 
    bar2(std::index_sequence_for<Types...,Types...>(), values...); 
} 

int main() 
{ 
    bar("Hallo", 42, 1.23); 
} 

Live example

Nó hiện đang zero-based, nhưng một +1 ở đúng nơi sẽ khắc phục điều đó một cách dễ dàng. Ngoài ra, nó tạo ra một trung gian std::tuple với tham chiếu đến các giá trị, nếu hiệu suất là một vấn đề tùy chọn tốt hơn có thể tồn tại nhưng kể từ khi bạn không sử dụng std::forward tôi figured rằng một tác động hiệu suất nhỏ có thể chấp nhận được cho bạn.

+0

Tôi đã tìm được một bộ tuple-of-2-tuple, sau đó làm phẳng, trở thành của tôi cách tiếp cận mặc định. Trong C++ 17, tôi có thể sử dụng 'if constexpr',' tupler', lambda và 'std :: apply' để thực hiện cuộc gọi nội tuyến, điều này thực sự thú vị. – Yakk

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