วิธีการจำลองการเริ่มต้นอาร์เรย์ C“ int arr [] = {e1, e2, e3, …}” พฤติกรรมกับ std :: array?


137

(หมายเหตุ: คำถามนี้เป็นคำถามเกี่ยวกับการไม่ต้องระบุจำนวนขององค์ประกอบและยังคงอนุญาตให้มีชนิดที่ซ้อนกันที่จะเริ่มต้นได้โดยตรง.)
คำถามนี้กล่าวถึงการใช้งานที่เหลือสำหรับอาร์เรย์ C int arr[20];เช่น ในคำตอบของเขา @James Kanze แสดงหนึ่งในฐานที่มั่นสุดท้ายของอาร์เรย์ C มันเป็นลักษณะการเริ่มต้นที่ไม่ซ้ำกัน:

int arr[] = { 1, 3, 3, 7, 0, 4, 2, 0, 3, 1, 4, 1, 5, 9 };

เราไม่ต้องระบุจำนวนองค์ประกอบไชโย! ทีนี้วนซ้ำด้วยฟังก์ชัน C ++ 11 std::beginและstd::endจาก<iterator>( หรือตัวแปรของคุณเอง ) และคุณไม่จำเป็นต้องคิดถึงขนาดของมัน

ตอนนี้มีวิธีใดบ้าง (ที่เป็นไปได้ของ TMP) ในการบรรลุเป้าหมายเดียวกันstd::arrayหรือไม่? อนุญาตให้ใช้มาโครเพื่อทำให้ดูดีขึ้น :)

??? std_array = { "here", "be", "elements" };

แก้ไข : เวอร์ชันกลางรวบรวมจากคำตอบที่หลากหลายมีลักษณะดังนี้:

#include <array>
#include <utility>

template<class T, class... Tail, class Elem = typename std::decay<T>::type>
std::array<Elem,1+sizeof...(Tail)> make_array(T&& head, Tail&&... values)
{
  return { std::forward<T>(head), std::forward<Tail>(values)... };
}

// in code
auto std_array = make_array(1,2,3,4,5);

และใช้งาน C ++ 11 สุดเจ๋งทุกชนิด:

  • เทมเพลต Variadic
  • sizeof...
  • การอ้างอิงค่า
  • ส่งต่อที่สมบูรณ์แบบ
  • std::array, แน่นอน
  • การเริ่มต้นเครื่องแบบ
  • ละเว้นประเภทส่งคืนด้วยการกำหนดค่าเริ่มต้นสม่ำเสมอ
  • การอนุมานประเภท ( auto)

และตัวอย่างที่สามารถพบได้ที่นี่

อย่างไรก็ตามเนื่องจาก @Johannes ชี้ให้เห็นในความคิดเห็นเกี่ยวกับคำตอบของ @ Xaade คุณจะไม่สามารถเริ่มต้นประเภทซ้อนกันได้ด้วยฟังก์ชันดังกล่าว ตัวอย่าง:

struct A{ int a; int b; };

// C syntax
A arr[] = { {1,2}, {3,4} };
// using std::array
??? std_array = { {1,2}, {3,4} };

นอกจากนี้จำนวนของ initializers ถูก จำกัด ไว้ที่จำนวนฟังก์ชันและอาร์กิวเมนต์เทมเพลตที่สนับสนุนโดยการนำไปใช้งาน


วิธี Variadic มันไม่ใช่การเริ่มต้นเช่นการมอบหมาย แต่มันใกล้เคียงที่สุดที่ฉันสามารถมาได้ ในการรับการเริ่มต้นคุณจะต้องเข้าถึงหน่วยความจำโดยตรง
Lee Louviere

เห็นได้ชัดว่า C ++ 0x รองรับไวยากรณ์เริ่มต้น น่ากลัว มันเหมือนกับว่าได้เป็นเหมือน C # มากขึ้นด้วยการสนับสนุนทางภาษาเพื่อการสนับสนุนที่ซับซ้อนมากขึ้น ใครรู้ว่าเราได้รับการสนับสนุนอย่างเป็นทางการภาษาสำหรับอินเตอร์เฟซ
Lee Louviere

10
@Downvoter: เหตุผลล่ะ
Xeo

1
ขออภัยความหมายของTMPคำถามของคุณคืออะไร
kevinarpe

คำตอบ:


63

ดีที่สุดที่ฉันคิดได้คือ:

template<class T, class... Tail>
auto make_array(T head, Tail... tail) -> std::array<T, 1 + sizeof...(Tail)>
{
     std::array<T, 1 + sizeof...(Tail)> a = { head, tail ... };
     return a;
}

auto a = make_array(1, 2, 3);

อย่างไรก็ตามสิ่งนี้ต้องการคอมไพเลอร์ในการทำ NRVO แล้วข้ามสำเนาของค่าที่ส่งคืน (ซึ่งเป็นกฎหมาย แต่ไม่จำเป็น) ในทางปฏิบัติฉันคาดหวังว่าคอมไพเลอร์ C ++ ใด ๆ ที่จะสามารถเพิ่มประสิทธิภาพได้อย่างรวดเร็วเท่ากับการเริ่มต้นโดยตรง


gcc 4.6.0 ไม่อนุญาตให้คอมไพล์อันที่สองบ่นเกี่ยวกับการลดการแปลงจาก double เป็น value_type แต่ clang ++ 2.9 นั้นใช้ได้กับทั้งคู่!
Cubbi

21
มันมีคำตอบเช่นนี้ที่ฉันเข้าใจว่าสิ่งที่ Bjarne พูดเกี่ยวกับความรู้สึก "เหมือนภาษาใหม่" :) เทมเพลต Variadic ตัวระบุการส่งคืนสายและการหักประเภท all-in-one!
Matthieu M.

@Matthieu: ตอนนี้เพิ่มการอ้างอิงค่า rvalue การส่งต่อที่สมบูรณ์แบบและการเริ่มต้นที่สม่ำเสมอจากรหัสของ @ DeadMG และคุณมีคุณสมบัติใหม่มากมาย :>
Xeo

1
@Cubbi: อันที่จริงแล้ว g ++ อยู่ที่นี่ - ไม่อนุญาตให้ทำการแปลงที่แคบลงในการเริ่มต้นรวมใน C ++ 0x (แต่อนุญาตใน C ++ 03 - การเปลี่ยนแปลงที่ผิดที่ฉันไม่ทราบ!) ฉันจะลบmake_arrayสายที่สอง
Pavel Minaev

@ Cubbi ใช่ แต่นั่นเป็นการแปลงที่ชัดเจน - มันยังอนุญาตให้ downcast แบบเงียบและสิ่งอื่น ๆ สิ่งนี้ยังสามารถทำได้โดยใช้static_assertและ TMP บางตัวในการตรวจสอบเมื่อTailไม่สามารถแปลงเป็นโดยปริยายTแล้วจากการใช้T(tail)...แต่เหลืออยู่ เป็นแบบฝึกหัดสำหรับผู้อ่าน :)
Pavel Minaev

39

make_arrayฉันคาดหวังที่เรียบง่าย

template<typename ret, typename... T> std::array<ret, sizeof...(T)> make_array(T&&... refs) {
    // return std::array<ret, sizeof...(T)>{ { std::forward<T>(refs)... } };
    return { std::forward<T>(refs)... };
}

1
เอาstd::array<ret, sizeof...(T)>ในreturnคำสั่ง นั่นเป็นการบังคับให้ constructor ของการย้ายบนประเภทอาร์เรย์มีอยู่ (ตรงข้ามกับ construct-from- T&&) ใน C ++ 14 และ C ++ 11
Yakk - Adam Nevraumont

8
ฉันชอบที่คน C ++ เรียกง่ายๆว่า :-)
Ciro Santilli 郝海东冠状病六四事件法轮功

20

การรวมแนวคิดบางประการจากการโพสต์ก่อนหน้านี้เป็นวิธีแก้ปัญหาที่ใช้ได้แม้กับการสร้างแบบซ้อน (ทดสอบใน GCC4.6):

template <typename T, typename ...Args>
std::array<T, sizeof...(Args) + 1> make_array(T && t, Args &&... args)
{
  static_assert(all_same<T, Args...>::value, "make_array() requires all arguments to be of the same type."); // edited in
  return std::array<T, sizeof...(Args) + 1>{ std::forward<T>(t), std::forward<Args>(args)...};
}

น่าแปลกที่ไม่สามารถทำให้ค่าส่งคืนเป็นการอ้างอิงค่า rvalue ซึ่งไม่สามารถใช้กับการสร้างแบบซ้อนได้ อย่างไรก็ตามนี่คือการทดสอบ:

auto q = make_array(make_array(make_array(std::string("Cat1"), std::string("Dog1")), make_array(std::string("Mouse1"), std::string("Rat1"))),
                    make_array(make_array(std::string("Cat2"), std::string("Dog2")), make_array(std::string("Mouse2"), std::string("Rat2"))),
                    make_array(make_array(std::string("Cat3"), std::string("Dog3")), make_array(std::string("Mouse3"), std::string("Rat3"))),
                    make_array(make_array(std::string("Cat4"), std::string("Dog4")), make_array(std::string("Mouse4"), std::string("Rat4")))
                    );

std::cout << q << std::endl;
// produces: [[[Cat1, Dog1], [Mouse1, Rat1]], [[Cat2, Dog2], [Mouse2, Rat2]], [[Cat3, Dog3], [Mouse3, Rat3]], [[Cat4, Dog4], [Mouse4, Rat4]]]

(สำหรับผลลัพธ์สุดท้ายที่ฉันใช้เครื่องพิมพ์สวยของฉัน)


ที่จริงให้เราปรับปรุงความปลอดภัยประเภทของการก่อสร้างนี้ เราต้องการทุกประเภทให้เหมือนกันแน่นอน วิธีหนึ่งคือการเพิ่มการยืนยันแบบคงที่ซึ่งฉันได้แก้ไขในข้างต้น วิธีอื่นคือเปิดใช้งานเฉพาะmake_arrayเมื่อชนิดเหมือนกันดังนี้:

template <typename T, typename ...Args>
typename std::enable_if<all_same<T, Args...>::value, std::array<T, sizeof...(Args) + 1>>::type
make_array(T && t, Args &&... args)
{
  return std::array<T, sizeof...(Args) + 1> { std::forward<T>(t), std::forward<Args>(args)...};
}

ไม่ว่าด้วยวิธีใดคุณจะต้องมีall_same<Args...>ลักษณะประเภทVariadic นี่มันเป็น generalizing จากstd::is_same<S, T>(ทราบว่าเนื้อที่เป็นสิ่งสำคัญที่จะช่วยให้การผสมของT, T&, T const &ฯลฯ ):

template <typename ...Args> struct all_same { static const bool value = false; };
template <typename S, typename T, typename ...Args> struct all_same<S, T, Args...>
{
  static const bool value = std::is_same<typename std::decay<S>::type, typename std::decay<T>::type>::value && all_same<T, Args...>::value;
};
template <typename S, typename T> struct all_same<S, T>
{
  static const bool value = std::is_same<typename std::decay<S>::type, typename std::decay<T>::type>::value;
};
template <typename T> struct all_same<T> { static const bool value = true; };

โปรดทราบว่าmake_array()ผลตอบแทนจากการคัดลอกชั่วคราวซึ่งคอมไพเลอร์ (มีการเพิ่มประสิทธิภาพที่เพียงพอ!) ได้รับอนุญาตให้ใช้เป็นค่า rvalue หรือปรับให้เหมาะสมและstd::arrayเป็นประเภทรวมดังนั้นคอมไพเลอร์จึงมีอิสระในการเลือกวิธีการก่อสร้างที่ดีที่สุด .

ท้ายที่สุดโปรดทราบว่าคุณไม่สามารถหลีกเลี่ยงการสร้างสำเนา / ย้ายเมื่อmake_arrayตั้งค่า initializer ดังนั้นstd::array<Foo,2> x{Foo(1), Foo(2)};ยังไม่มีการคัดลอก / ย้าย แต่auto x = make_array(Foo(1), Foo(2));มีสองคัดลอก / make_arrayย้ายเป็นข้อโต้แย้งที่มีการส่งต่อไปยัง ฉันไม่คิดว่าคุณจะสามารถปรับปรุงได้เพราะคุณไม่สามารถส่งรายการตัวกำหนดค่าเริ่มต้นแบบแปรผันไปยังผู้ช่วยและประเภทและขนาดได้ - ถ้าตัวประมวลผลล่วงหน้ามีsizeof...ฟังก์ชันสำหรับการขัดแย้งแบบแปรปรวนบางทีอาจทำได้ แต่ไม่ใช่ ภายในภาษาหลัก


13

การใช้ไวยากรณ์ผลตอบแทนต่อท้ายmake_arrayสามารถทำให้ง่ายขึ้น

#include <array>
#include <type_traits>
#include <utility>

template <typename... T>
auto make_array(T&&... t)
  -> std::array<std::common_type_t<T...>, sizeof...(t)>
{
  return {std::forward<T>(t)...};
}

int main()
{
  auto arr = make_array(1, 2, 3, 4, 5);
  return 0;
}

โชคไม่ดีสำหรับคลาสรวมที่ต้องมีการกำหนดประเภทที่ชัดเจน

/*
struct Foo
{
  int a, b;
}; */

auto arr = make_array(Foo{1, 2}, Foo{3, 4}, Foo{5, 6});

ในความเป็นจริงmake_arrayการใช้งานนี้มีการระบุไว้ในsizeof ... ผู้ประกอบการ


รุ่น c ++ 17

ขอบคุณการหักล้างอาร์กิวเมนต์เทมเพลตสำหรับข้อเสนอเทมเพลตชั้นเรียนเราสามารถใช้คู่มือการหักเงินเพื่อกำจัดmake_arrayผู้ช่วย

#include <array>

namespace std
{
template <typename... T> array(T... t)
  -> array<std::common_type_t<T...>, sizeof...(t)>;
}

int main()
{
  std::array a{1, 2, 3, 4};
  return 0; 
}

คอมไพล์ด้วย-std=c++1zแฟล็กภายใต้ x86-64 gcc 7.0


6
C ++ 17 ควรมีคำแนะนำการหักเงินสำหรับสิ่งนี้แล้ว: en.cppreference.com/w/cpp/container/array/deduction_guides
underscore_d

6

ฉันรู้ว่ามันค่อนข้างบางครั้งตั้งแต่คำถามนี้ถูกถาม แต่ฉันรู้สึกว่าคำตอบที่มีอยู่ยังคงมีข้อบกพร่องบางอย่างดังนั้นฉันต้องการเสนอเวอร์ชันที่แก้ไขเล็กน้อยของฉัน ต่อไปนี้เป็นจุดที่ฉันคิดว่าคำตอบที่มีอยู่หายไป


1. ไม่จำเป็นต้องพึ่งพา RVO

คำตอบบางอย่างพูดถึงว่าเราจำเป็นต้องพึ่งพา RVO arrayที่จะกลับมาสร้าง นั่นไม่เป็นความจริง เราสามารถใช้ประโยชน์จากการคัดลอกรายการเริ่มต้นเพื่อรับประกันว่าจะไม่มีการสร้างชั่วคราว ดังนั้นแทนที่จะ:

return std::array<Type, …>{values};

เราควรทำ:

return {{values}};

2. ฟังก์ชั่นmake_arrayconstexpr

สิ่งนี้ช่วยให้เราสามารถสร้างอาร์เรย์คงที่เวลาคอมไพล์

3. ไม่จำเป็นต้องตรวจสอบว่าข้อโต้แย้งทั้งหมดเป็นประเภทเดียวกัน

ก่อนอื่นหากไม่ได้คอมไพเลอร์จะออกคำเตือนหรือข้อผิดพลาดเนื่องจากรายการเริ่มต้นไม่อนุญาตให้แคบลง ประการที่สองแม้ว่าเราจะตัดสินใจทำเองstatic_assertสิ่งของ (อาจจะให้ข้อความแสดงข้อผิดพลาดที่ดีกว่า) เราก็ควรจะเปรียบเทียบประเภทการสลายตัวของอาร์กิวเมนต์มากกว่าประเภทดิบ ตัวอย่างเช่น,

volatile int a = 0;
const int& b = 1;
int&& c = 2;

auto arr = make_array<int>(a, b, c);  // Will this work?

ถ้าเราแค่static_assertคิดว่าaกล่าวbและcมีประเภทเดียวกันการตรวจสอบนี้จะล้มเหลว แต่อาจไม่ใช่สิ่งที่เราคาดหวัง แต่เราควรเปรียบเทียบstd::decay_t<T>ประเภทของพวกเขา(ซึ่งเป็นทั้งหมดint)

4. ลดค่าประเภทอาเรย์โดยการแยกอาร์กิวเมนต์ที่ส่งต่อ

สิ่งนี้คล้ายกับจุดที่ 3 การใช้โค้ดขนาดเดียวกัน แต่ไม่ได้ระบุประเภทค่าอย่างชัดเจนในเวลานี้:

volatile int a = 0;
const int& b = 1;
int&& c = 2;

auto arr = make_array(a, b, c);  // Will this work?

เราอาจต้องการที่จะทำให้ array<int, 3>แต่การใช้งานในคำตอบที่มีอยู่อาจทั้งหมดล้มเหลวในการทำเช่นนั้น สิ่งที่เราสามารถทำได้คือแทนที่จะกลับstd::array<T, …>, std::array<std::decay_t<T>, …>กลับ

มีข้อเสียอย่างหนึ่งเกี่ยวกับวิธีการนี้: เราไม่สามารถส่งคืนarrayประเภทค่าที่ผ่านการรับรองด้วย cv ได้อีกต่อไป แต่ส่วนใหญ่แทนที่จะเป็นอะไรarray<const int, …>เราจะใช้มันconst array<int, …>ต่อไป มีการแลกเปลี่ยน แต่ฉันคิดว่าเหมาะสม C ++ 17 std::make_optionalใช้แนวทางนี้เช่นกัน:

template< class T > 
constexpr std::optional<std::decay_t<T>> make_optional( T&& value );

เมื่อคำนึงถึงประเด็นข้างต้นแล้วการใช้งานอย่างเต็มรูปแบบของmake_arrayใน C ++ 14 มีลักษณะดังนี้:

#include <array>
#include <type_traits>
#include <utility>

template<typename T, typename... Ts>
constexpr std::array<std::decay_t<T>, 1 + sizeof... (Ts)>
make_array(T&& t, Ts&&... ts)
    noexcept(noexcept(std::is_nothrow_constructible<
                std::array<std::decay_t<T>, 1 + sizeof... (Ts)>, T&&, Ts&&...
             >::value))

{
    return {{std::forward<T>(t), std::forward<Ts>(ts)...}};
}

template<typename T>
constexpr std::array<std::decay<T>_t, 0> make_array() noexcept
{
    return {};
}

การใช้งาน:

constexpr auto arr = make_array(make_array(1, 2),
                                make_array(3, 4));
static_assert(arr[1][1] == 4, "!");

6

C ++ 11 จะรองรับลักษณะของการเริ่มต้นสำหรับคอนเทนเนอร์มาตรฐาน (ส่วนใหญ่)


1
อย่างไรก็ตามฉันคิดว่า OP ไม่ต้องการระบุขนาดของอาร์เรย์ แต่ขนาดเป็นพารามิเตอร์เทมเพลตของ std :: array ดังนั้นคุณต้องการบางสิ่งเช่น std :: array <int ที่ไม่ได้ลงนาม 5> n = {1,2,3,4,5};
juanchopanza

std::vector<>ไม่จำเป็นต้องเป็นจำนวนเต็มอย่างชัดเจนและผมไม่แน่ใจว่าทำไมstd::arrayจะ
Richard

@Richard เนื่องจาก std :: vector มีขนาดแบบไดนามิกและ std :: array มีขนาดคงที่ ดูสิ่งนี้: en.wikipedia.org/wiki/Array_(C%2B%2B)
juanchopanza

@juanchopanza แต่{...}ไวยากรณ์หมายถึงขอบเขตคงที่เวลาคอมไพล์ดังนั้น ctor ควรจะสามารถสรุปขอบเขตได้
Richard

1
std::initializer_list::sizeไม่ใช่constexprฟังก์ชั่นและไม่สามารถใช้งานได้เช่นนี้ มีแผนอย่างไรจาก libstdc ++ (จัดส่งดำเนินการกับ GCC) constexprที่จะมีรุ่นของพวกเขา
Luc Danton

5

(โซลูชันโดย @dyp)

หมายเหตุ: ต้องใช้C ++ 14 ( std::index_sequence) แม้ว่าหนึ่งสามารถใช้std::index_sequenceใน C ++ 11

#include <iostream>

// ---

#include <array>
#include <utility>

template <typename T>
using c_array = T[];

template<typename T, size_t N, size_t... Indices>
constexpr auto make_array(T (&&src)[N], std::index_sequence<Indices...>) {
    return std::array<T, N>{{ std::move(src[Indices])... }};
}

template<typename T, size_t N>
constexpr auto make_array(T (&&src)[N]) {
    return make_array(std::move(src), std::make_index_sequence<N>{});
}

// ---

struct Point { int x, y; };

std::ostream& operator<< (std::ostream& os, const Point& p) {
    return os << "(" << p.x << "," << p.y << ")";
}

int main() {
    auto xs = make_array(c_array<Point>{{1,2}, {3,4}, {5,6}, {7,8}});

    for (auto&& x : xs) {
        std::cout << x << std::endl;
    }

    return 0;
}

ฉันมองข้ามการเริ่มต้นเริ่มต้นขององค์ประกอบ std :: array กำลังมองหาวิธีแก้ไข
Gabriel Garcia

@dyp ฉันอัปเดตคำตอบด้วยรหัสของคุณ หากคุณตัดสินใจที่จะเขียนคำตอบของคุณเองให้ฉันรู้และฉันจะทำให้ฉันผิดหวัง ขอบคุณ.
Gabriel Garcia

1
ไม่เป็นไร. การผูกอาเรย์ชั่วคราวเพื่ออนุมานความยาวนั้นเป็นความคิดของคุณและฉันไม่ได้ตรวจสอบว่ารหัสของฉันรวบรวมได้หรือไม่ ฉันคิดว่ามันยังคงเป็นทางออกของคุณและตอบด้วยการปรับแต่ง;) บางคนอาจโต้เถียงแม้ว่าจะไม่มีประโยชน์ที่จะได้รับความแตกต่างmake_arrayเหมือนในคำตอบของลูกสุนัขแม้ว่า
dyp

ขวา. ยิ่งกว่านั้นเท็มเพลตไม่สามารถอนุมานประเภทจากรายการ initializer ซึ่งเป็นหนึ่งในข้อกำหนดของคำถาม
Gabriel Garcia

1

С ++ 17 การติดตั้งใช้งานที่กะทัดรัด

template <typename... T>
constexpr auto array_of(T&&... t) {
    return std::array{ static_cast<std::common_type_t<T...>>(t)... };
}

0

หากมาตรฐาน :: อาร์เรย์ไม่ได้เป็นข้อ จำกัด และถ้าคุณมี Boost list_of()นั้นจะดูที่ สิ่งนี้ไม่เหมือนกับการกำหนดค่าเริ่มต้นของอาร์เรย์ชนิด C ที่คุณต้องการ แต่ใกล้เคียง


นั่นเป็นสิ่งที่ดี และคำถามที่คล้ายกันเกี่ยวกับการใช้มันสำหรับการกำหนดโครงสร้างซ้อนกันอยู่ที่นี่การใช้กำหนดแผนที่รายชื่อของสำหรับประเภทที่ซับซ้อน
Assambar

0

สร้างประเภทผู้สร้างอาร์เรย์

มันเกินพิกัด operator,เพื่อสร้างเทมเพลตนิพจน์ที่เชื่อมโยงแต่ละองค์ประกอบเข้ากับหน้าที่ผ่านการอ้างอิง

เพิ่ม finishฟังก์ชั่นฟรีที่จะนำผู้สร้างอาร์เรย์และสร้างอาร์เรย์โดยตรงจากห่วงโซ่การอ้างอิง

ไวยากรณ์ควรมีลักษณะดังนี้:

auto arr = finish( make_array<T>->* 1,2,3,4,5 );

มันไม่อนุญาตให้มี{}การก่อสร้างตามเป็นเพียงoperator=ไม่ หากคุณยินดีที่จะใช้=เราสามารถทำให้มันใช้ได้

auto arr = finish( make_array<T>= {1}={2}={3}={4}={5} );

หรือ

auto arr = finish( make_array<T>[{1}][{2}[]{3}][{4}][{5}] );

ไม่มีลักษณะเหล่านี้เหมือนโซลูชันที่ดี

การใช้ Variardics จำกัด คุณไว้ที่ขีด จำกัด ที่คอมไพเลอร์กำหนดจำนวน varargs และบล็อกการใช้ recursive {}สำหรับโครงสร้างย่อย

ในท้ายที่สุดมันก็ไม่ใช่ทางออกที่ดี

สิ่งที่ฉันทำคือฉันเขียนโค้ดของฉันดังนั้นมันจึงใช้ทั้งข้อมูลT[]และแบบagnostically - มันไม่สนใจว่าฉันจะป้อนข้อมูลอะไร บางครั้งนี่หมายความว่ารหัสการส่งต่อของฉันต้องเปลี่ยนArray ให้เป็นโปร่งใสstd::array[]std::array


1
"สิ่งเหล่านี้ดูเหมือนโซลูชันที่ดี" คือสิ่งที่ฉันจะพูดเช่นกัน: p
caps
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.