รูปแบบโค้ด HIDL คล้ายกับโค้ด C++ ในเฟรมเวิร์ก Android โดยมีเว้นวรรค 4 ช่อง การเยื้องและชื่อไฟล์ที่มีตัวพิมพ์เล็กและใหญ่ผสมกัน การประกาศแพ็กเกจ การนําเข้า และเอกสารสตริง คล้ายกับใน Java โดยมีการแก้ไขเล็กน้อย
ตัวอย่างต่อไปนี้สำหรับ IFoo.hal
และ types.hal
แสดงรูปแบบโค้ด HIDL และใส่ลิงก์ด่วนไปยังรายละเอียดของแต่ละสไตล์
(IFooClientCallback.hal
, IBar.hal
และ
ละเว้น IBaz.hal
)
hardware/interfaces/foo/1.0/IFoo.hal |
---|
/* |
hardware/interfaces/foo/1.0/types.hal |
---|
/* |
รูปแบบการตั้งชื่อ
ชื่อฟังก์ชัน ชื่อตัวแปร และชื่อไฟล์ควรสื่อความหมาย หลีกเลี่ยง
ใช้ตัวย่อมากเกินไป พิจารณาตัวย่อเป็นคำ (เช่น ใช้ INfc
แทน
ของ INFC
)
โครงสร้างไดเรกทอรีและการตั้งชื่อไฟล์
โครงสร้างไดเรกทอรีควรปรากฏดังนี้
ROOT-DIRECTORY
MODULE
SUBMODULE
(ไม่บังคับ อาจมีมากกว่า 1 รายการ ระดับ)VERSION
Android.mk
IINTERFACE_1.hal
IINTERFACE_2.hal
…
IINTERFACE_N.hal
types.hal
(ไม่บังคับ)
สถานที่:
ROOT-DIRECTORY
คือhardware/interfaces
สำหรับแพ็กเกจ HIDL หลักvendor/VENDOR/interfaces
สำหรับแพ็กเกจผู้ให้บริการ โดยที่VENDOR
หมายถึงผู้ให้บริการ SoC หรือ OEM/ODM
MODULE
ควรเป็นคำตัวพิมพ์เล็ก 1 คำที่อธิบาย ระบบย่อย (เช่นnfc
) หากต้องการคำมากกว่า 1 คำ ให้ใช้SUBMODULE
ที่ฝังไว้ สามารถมีระดับของ การซ้อนกันVERSION
ควรเป็นเวอร์ชันเดียวกันทั้งหมด (major.minor) ตามที่อธิบายไว้ในเวอร์ชันIINTERFACE_X
ควรเป็นชื่ออินเทอร์เฟซที่มีUpperCamelCase
/PascalCase
(เช่นINfc
) ตามที่อธิบายไว้ในชื่ออินเทอร์เฟซ
ตัวอย่าง
hardware/interfaces
nfc
1.0
Android.mk
INfc.hal
INfcClientCallback.hal
types.hal
หมายเหตุ: ไฟล์ทั้งหมดต้องมีไฟล์ที่เป็นไฟล์ปฏิบัติการ สิทธิ์ (ใน Git)
ชื่อแพ็กเกจ
ชื่อแพ็กเกจต้องใช้ชื่อที่สมบูรณ์ในตัวเองต่อไปนี้
(FQN) (เรียกว่า PACKAGE-NAME
)
PACKAGE .MODULE [.SUBMODULE [.SUBMODULE […]]]@VERSION
สถานที่:
PACKAGE
เป็นแพ็กเกจที่แมปกับROOT-DIRECTORY
โดยเฉพาะอย่างยิ่งPACKAGE
คือandroid.hardware
สำหรับแพ็กเกจ HIDL หลัก (แมปกับhardware/interfaces
)vendor.VENDOR.hardware
สำหรับแพ็กเกจผู้ให้บริการ โดยที่VENDOR
หมายถึงผู้ให้บริการ SoC หรือ OEM/ODM (การแมปvendor/VENDOR/interfaces
)
MODULE[.SUBMODULE[.SUBMODULE[…]]]@VERSION
เป็นชื่อโฟลเดอร์เดียวกันกับในโครงสร้างที่อธิบาย โครงสร้างไดเรกทอรี- ชื่อแพ็กเกจควรเป็นตัวพิมพ์เล็ก หากยาวกว่า 1 คำ ระบบจะ
ควรใช้คำเป็นโมดูลย่อยหรือเขียนด้วย
snake_case
- ไม่อนุญาตให้ใช้เว้นวรรค
FQN จะใช้ในการประกาศแพ็กเกจเสมอ
เวอร์ชัน
เวอร์ชันควรมีรูปแบบต่อไปนี้
MAJOR .MINOR
ทั้งเวอร์ชัน MAJOR และ MINOR ควรเป็นเวอร์ชันเดียว จำนวนเต็ม HIDL ใช้ความหมาย การกำหนดเวอร์ชัน
การนำเข้า
การนำเข้ามี 1 ใน 3 รูปแบบต่อไปนี้
- การนำเข้าทั้งแพ็กเกจ:
import PACKAGE-NAME;
- การนําเข้าบางส่วน:
import PACKAGE-NAME::UDT;
(หรือหากการนําเข้า ที่อยู่ในแพ็กเกจเดียวกันimport UDT;
- การนำเข้าประเภทเท่านั้น:
import PACKAGE-NAME::types;
PACKAGE-NAME
มีรูปแบบใน
ชื่อแพ็กเกจ แพ็กเกจปัจจุบัน
types.hal
(หากมี) จะถูกนำเข้าโดยอัตโนมัติ (ไม่ต้องนำเข้า
อย่างชัดเจน)
ชื่อที่มีคุณสมบัติครบถ้วน (FQN)
ใช้ชื่อที่สมบูรณ์ในตัวเองสำหรับการนำเข้าประเภทที่ผู้ใช้กำหนดเมื่อจำเป็นเท่านั้น
ละเว้น PACKAGE-NAME
หากประเภทการนำเข้าเหมือนกัน
ใหม่ FQN ต้องไม่มีการเว้นวรรค ตัวอย่างชื่อที่สมบูรณ์ในตัวเอง:
android.hardware.nfc@1.0::INfcClientCallback
ในไฟล์อื่นภายใต้ android.hardware.nfc@1.0
ให้อ้างอิง
เหนืออินเทอร์เฟซเป็น INfcClientCallback
หรือไม่เช่นนั้น ให้ใช้เฉพาะ
ชื่อที่มีคุณสมบัติครบถ้วน
การจัดกลุ่มและสั่งซื้อการนำเข้า
ใช้บรรทัดว่างหลังการประกาศแพ็กเกจ (ก่อนการนำเข้า) การนำเข้าแต่ละครั้ง ควรใช้พื้นที่บรรทัดเดียวและไม่ควรเยื้อง จัดกลุ่มการนำเข้าใน คำสั่งซื้อต่อไปนี้:
- แพ็กเกจอื่นๆ อีก
android.hardware
รายการ (ใช้ชื่อที่สมบูรณ์ในตัวเอง) - แพ็กเกจอื่นๆ
vendor.VENDOR
รายการ (ใช้คุณสมบัติแบบเต็ม) ชื่อ)- ผู้ให้บริการแต่ละรายควรเป็นกลุ่ม
- เรียงลำดับผู้ให้บริการตามตัวอักษร
- การนำเข้าจากอินเทอร์เฟซอื่นในแพ็กเกจเดียวกัน (ใช้ชื่อแบบง่าย)
ขึ้นบรรทัดว่างระหว่างกลุ่ม ในแต่ละกลุ่ม ให้จัดเรียงการนำเข้า ตามลำดับตัวอักษร ตัวอย่าง
import android.hardware.nfc@1.0::INfc;
import android.hardware.nfc@1.0::INfcClientCallback;
/* Importing the whole module. */
import vendor.barvendor.bar@3.1;
import vendor.foovendor.foo@2.2::IFooBar;
import vendor.foovendor.foo@2.2::IFooFoo;
import IBar;
import IFoo;
ชื่ออินเทอร์เฟซ
ชื่ออินเทอร์เฟซต้องขึ้นต้นด้วย I
ตามด้วย
UpperCamelCase
/PascalCase
ชื่อ อินเทอร์เฟซที่มีชื่อ
ต้องกำหนด IFoo
ในไฟล์ IFoo.hal
ไฟล์นี้
มีคําจํากัดความของอินเทอร์เฟซ IFoo
เท่านั้น (อินเทอร์เฟซ
INAME
ควรอยู่ใน INAME.hal
)
ฟังก์ชัน
สำหรับชื่อฟังก์ชัน อาร์กิวเมนต์ และชื่อตัวแปรผลลัพธ์ ให้ใช้
lowerCamelCase
ตัวอย่าง
open(INfcClientCallback clientCallback) generates (int32_t retVal);
oneway pingAlive(IFooCallback cb);
ชื่อช่องสำหรับโครงสร้างและการรวม
สำหรับชื่อช่องโครงสร้างหรือการรวม ให้ใช้ lowerCamelCase
ตัวอย่าง
struct FooReply {
vec<uint8_t> replyData;
}
พิมพ์ชื่อ
ชื่อประเภทหมายถึงคำจำกัดความของโครงสร้างหรือการรวม คำจำกัดความของประเภท enum และ
typedef
วินาที สำหรับชื่อเหล่านี้ ให้ใช้
UpperCamelCase
/PascalCase
ตัวอย่าง:
enum NfcStatus : int32_t {
/*...*/
};
struct NfcData {
/*...*/
};
ค่า enum
ค่า enum ควรเป็น UPPER_CASE_WITH_UNDERSCORES
เมื่อผ่าน
ค่า enum เป็นอาร์กิวเมนต์ของฟังก์ชัน แล้วแสดงผลเป็นฟังก์ชันส่งคืน ใช้
ประเภท enum จริง (ไม่ใช่ประเภทจำนวนเต็มที่แฝงอยู่) ตัวอย่าง
enum NfcStatus : int32_t {
HAL_NFC_STATUS_OK = 0,
HAL_NFC_STATUS_FAILED = 1,
HAL_NFC_STATUS_ERR_TRANSPORT = 2,
HAL_NFC_STATUS_ERR_CMD_TIMEOUT = 3,
HAL_NFC_STATUS_REFUSED = 4
};
หมายเหตุ: ประเภทที่สำคัญของประเภท enum คือ ที่ประกาศอย่างชัดเจนหลังเครื่องหมายโคลอน เนื่องจากไม่ต้องพึ่งคอมไพเลอร์ การใช้ ประเภท enum จริงจะชัดเจนกว่า
สำหรับชื่อที่สมบูรณ์ในตัวเองของค่า enum ระบบจะใช้ colon แทน ระหว่างชื่อประเภท enum กับชื่อค่า enum ดังนี้
PACKAGE-NAME ::UDT [.UDT [.UDT […]]:ENUM_VALUE_NAME
ต้องไม่มีการเว้นวรรคในชื่อที่สมบูรณ์ในตัวเอง ใช้ URL แบบเต็ม ในกรณีที่จำเป็น และละเว้นส่วนที่ไม่จำเป็นเท่านั้น ตัวอย่าง
android.hardware.foo@1.0::IFoo.IFooInternal.FooEnum:ENUM_OK
ความคิดเห็น
สำหรับความคิดเห็นแบบบรรทัดเดียวคือ //
, /* */
และ /** */
ก็ไม่เป็นไร
// This is a single line comment
/* This is also single line comment */
/** This is documentation comment */
-
ใช้
/* */
สำหรับแสดงความคิดเห็น แม้ว่า HIDL จะรองรับความคิดเห็น//
ซึ่งไม่แสดงในเอาต์พุตที่สร้างขึ้น - ใช้
/** */
สำหรับเอกสารที่สร้างขึ้น คุณใช้วิธีเหล่านี้ได้ เพื่อประกาศค่า Method ฟิลด์ และ enum เท่านั้น ตัวอย่าง/** Replied status */
enum TeleportStatus {
/** Object entirely teleported. */
OK = 0,
/** Methods return this if teleportation is not completed. */
ERROR_TELEPORT = 1,
/**
* Teleportation could not be completed due to an object
* obstructing the path.
*/
ERROR_OBJECT = 2,
...
} - เริ่มเขียนความคิดเห็นแบบหลายบรรทัดกับ
/**
ในอีกบรรทัดหนึ่ง ใช้*
ที่ต้นแต่ละบรรทัด จบความคิดเห็นด้วย*/
ในอีกบรรทัดหนึ่งโดยจัดวางเครื่องหมายดอกจัน ตัวอย่าง/**
* My multi-line
* comment
*/ - ประกาศการอนุญาตให้ใช้สิทธิและบันทึกการเปลี่ยนแปลงควรขึ้นบรรทัดใหม่ด้วย
/*
(ดอกจันเดี่ยว) ใช้*
นำหน้าแต่ละบรรทัด แล้วใส่*/
ในบรรทัดสุดท้ายอย่างเดียว (ดอกจันควรปรับแนว) ตัวอย่าง/*
* Copyright (C) 2017 The Android Open Source Project
* ...
*/
/*
* Changelog:
* ...
*/
ส่งความคิดเห็น
เริ่มต้นแต่ละไฟล์ด้วยประกาศการอนุญาตให้ใช้สิทธิที่เหมาะสม สำหรับ HAL หลัก
ควรเป็นใบอนุญาต AOSP Apache ใน
development/docs/copyright-templates/c.txt
อย่าลืมอัปเดตปีและใช้ความคิดเห็นแบบหลายบรรทัดในรูปแบบ /* */
ตามที่อธิบายไว้ข้างต้น
คุณสามารถเว้นบรรทัดว่างหลังการแจ้งเตือนใบอนุญาต แล้วตามด้วย
ด้วยบันทึกการเปลี่ยนแปลง/ข้อมูลเวอร์ชัน ใช้รูปแบบ /* */
ความคิดเห็นแบบหลายบรรทัดตามที่อธิบายไว้ข้างต้น ให้วางบรรทัดว่างหลัง
Changelog (บันทึกการเปลี่ยนแปลง) แล้วตามด้วยการประกาศแพ็กเกจ
ความคิดเห็นสิ่งที่ต้องทำ
สิ่งที่ต้องทำควรมีสตริง TODO
ในอักษรตัวพิมพ์ใหญ่ทั้งหมดตามด้วย
เครื่องหมายโคลอน ตัวอย่าง
// TODO: remove this code before foo is checked in.
อนุญาตให้ใช้ความคิดเห็น "สิ่งที่ต้องทำ" ในระหว่างการพัฒนาเท่านั้น พวกเขาต้อง ไม่อยู่ในอินเทอร์เฟซที่เผยแพร่
ความคิดเห็นในอินเทอร์เฟซและฟังก์ชัน (docstring)
ใช้ /** */
สำหรับ Docstring หลายบรรทัดและบรรทัดเดียว ไม่ใช้
//
สำหรับ docstring
Docstrings สำหรับอินเทอร์เฟซควรอธิบายกลไกทั่วไปของ อินเทอร์เฟซ เหตุผลในการออกแบบ วัตถุประสงค์ เป็นต้น การตัดทอนเอกสารสำหรับฟังก์ชันต่างๆ ควร เฉพาะสำหรับฟังก์ชันนั้นๆ (เอกสารประกอบระดับแพ็กเกจจะอยู่ในไฟล์ README ใน ไดเรกทอรีแพ็กเกจ)
/**
* IFooController is the controller for foos.
*/
interface IFooController {
/**
* Opens the controller.
*
* @return status HAL_FOO_OK if successful.
*/
open() generates (FooStatus status);
/** Close the controller. */
close();
};
คุณต้องเพิ่ม @param
และ @return
สําหรับแต่ละรายการ
พารามิเตอร์/ค่าผลลัพธ์:
- คุณต้องเพิ่ม
@param
สําหรับพารามิเตอร์แต่ละรายการ ควรเป็น ตามด้วยชื่อพารามิเตอร์ ตามด้วยสตริงเอกสาร - คุณต้องเพิ่ม
@return
สำหรับผลลัพธ์แต่ละค่า ทั้งนี้ ควรตามด้วยชื่อของค่าผลลัพธ์ ตามด้วย docstring
ตัวอย่าง
/**
* Explain what foo does.
*
* @param arg1 explain what arg1 is
* @param arg2 explain what arg2 is
* @return ret1 explain what ret1 is
* @return ret2 explain what ret2 is
*/
foo(T arg1, T arg2) generates (S ret1, S ret2);
การจัดรูปแบบกฎ
กฎการจัดรูปแบบทั่วไปได้แก่
- ความยาวของบรรทัด ข้อความแต่ละบรรทัดต้องมีข้อมูลไม่เกิน 100 คอลัมน์
- ช่องว่าง ไม่มีช่องว่างต่อท้ายบรรทัด บรรทัดว่าง ต้องไม่มีช่องว่าง
- Space กับ Tab ใช้เฉพาะช่องว่าง
- ขนาดการเยื้อง ใช้ช่องว่าง 4 ช่องสำหรับบล็อกและ เว้นวรรค 8 บรรทัดสำหรับการขึ้นบรรทัดใหม่
- วงเล็บปีกกา ยกเว้นหมายเหตุ
วงเล็บปีกกา open จะอยู่ในบรรทัดเดียวกันกับด้านบน
แต่วงเล็บปีกกา ปิด และเครื่องหมายเซมิโคลอนต่อไปนี้ใช้
ทั้งบรรทัด ตัวอย่าง
interface INfc {
close();
};
การประกาศแพ็กเกจ
การประกาศแพ็กเกจควรอยู่ที่ด้านบนของไฟล์หลังใบอนุญาต ควรครอบคลุมทั้งบรรทัด และไม่ควรเยื้อง แพ็กเกจคือ ที่ประกาศโดยใช้รูปแบบต่อไปนี้ (สำหรับการจัดรูปแบบชื่อ โปรดดู ชื่อแพ็กเกจ):
packagePACKAGE-NAME ;
ตัวอย่าง
package android.hardware.nfc@1.0;
การประกาศฟังก์ชัน
ชื่อฟังก์ชัน, พารามิเตอร์, generates
และผลลัพธ์ควร
ให้อยู่ในบรรทัดเดียวกันหากเหมาะสม ตัวอย่าง
interface IFoo {
/** ... */
easyMethod(int32_t data) generates (int32_t result);
};
หากจัดวางไม่ได้พอดีกับบรรทัดเดียวกัน ให้พยายามใส่พารามิเตอร์แล้วกลับไป
ในระดับการเยื้องเดียวกัน และแยก generate
เพื่อช่วย
เพื่อให้ผู้อ่านเห็นพารามิเตอร์และแสดงผลค่าได้อย่างรวดเร็ว ตัวอย่าง
interface IFoo {
suchALongMethodThatCannotFitInOneLine(int32_t theFirstVeryLongParameter,
int32_t anotherVeryLongParameter);
anEvenLongerMethodThatCannotFitInOneLine(int32_t theFirstLongParameter,
int32_t anotherVeryLongParameter)
generates (int32_t theFirstReturnValue,
int32_t anotherReturnValue);
superSuperSuperSuperSuperSuperSuperLongMethodThatYouWillHateToType(
int32_t theFirstVeryLongParameter, // 8 spaces
int32_t anotherVeryLongParameter
) generates (
int32_t theFirstReturnValue,
int32_t anotherReturnValue
);
/* method name is even shorter than 'generates' */
foobar(AReallyReallyLongType aReallyReallyLongParameter,
AReallyReallyLongType anotherReallyReallyLongParameter)
generates (ASuperLongType aSuperLongReturnValue, // 4 spaces
ASuperLongType anotherSuperLongReturnValue);
}
รายละเอียดเพิ่มเติม:
- วงเล็บเปิดจะอยู่ในบรรทัดเดียวกับชื่อฟังก์ชันเสมอ
- ต้องไม่มีการเว้นวรรคระหว่างชื่อฟังก์ชันและวงเล็บเปิด
- ไม่มีช่องว่างระหว่างวงเล็บและพารามิเตอร์ ยกเว้นหากมี เป็นฟีดระหว่างรายการโฆษณา
- หาก
generates
อยู่ในบรรทัดเดียวกับการปิดก่อนหน้า วงเล็บ เว้นวรรคก่อนหน้า หากgenerates
เท่ากัน เป็นวงเล็บเปิดถัดไป ตามด้วยการเว้นวรรค - จัดพารามิเตอร์และค่าผลลัพธ์ทั้งหมดให้สอดคล้องกัน (ถ้าเป็นไปได้)
- การเยื้องเริ่มต้นคือ 4 วรรค
- พารามิเตอร์ที่ตัดไปจะสอดคล้องกับพารามิเตอร์แรกในบรรทัดก่อนหน้า มิเช่นนั้นจะมีการเยื้อง 8 ช่องว่าง
คำอธิบายประกอบ
ใช้รูปแบบต่อไปนี้สำหรับคำอธิบายประกอบ
@annotate(keyword = value, keyword = {value, value, value})
จัดเรียงคำอธิบายประกอบตามลำดับตัวอักษร และใช้เว้นวรรครอบเครื่องหมายเท่ากับ ตัวอย่าง
@callflow(key = value)
@entry
@exit
ตรวจสอบว่าคำอธิบายประกอบครอบคลุมบรรทัดทั้งบรรทัด ตัวอย่าง
/* Good */
@entry
@exit
/* Bad */
@entry @exit
หากคำอธิบายประกอบไม่สามารถจัดวางในบรรทัดเดียวกันได้ ให้เยื้องตามด้วย 8 ช่อง ตัวอย่าง
@annotate(
keyword = value,
keyword = {
value,
value
},
keyword = value)
หากอาร์เรย์ค่าทั้งหมดไม่สามารถอยู่ในบรรทัดเดียวกันได้ ให้ใส่ตัวแบ่งบรรทัดต่อท้าย
วงเล็บปีกกาเปิด {
และหลังคอมมาแต่ละรายการภายในอาร์เรย์ การปิดสถานที่
วงเล็บหลังค่าสุดท้าย อย่าใส่วงเล็บปีกกาหากมี
ค่าเดียวเท่านั้น
หากอาร์เรย์ค่าทั้งหมดอยู่ในบรรทัดเดียวกันได้ โปรดอย่าเว้นวรรคหลัง วงเล็บปีกกาเปิดและก่อนวงเล็บปิด แล้วใช้ 1 ช่องว่างหลังเครื่องหมายคอมมาแต่ละรายการ ตัวอย่าง
/* Good */
@callflow(key = {"val", "val"})
/* Bad */
@callflow(key = { "val","val" })
ต้องไม่มีบรรทัดว่างระหว่างคำอธิบายประกอบและฟังก์ชัน ประกาศ ตัวอย่าง
/* Good */
@entry
foo();
/* Bad */
@entry
foo();
การประกาศ enum
ใช้กฎต่อไปนี้สำหรับการประกาศ Enum
- หากแชร์การประกาศ Enum กับแพ็กเกจอื่น ให้ใส่การประกาศ
ใน
types.hal
แทนการฝังภายในอินเทอร์เฟซ - ใช้การเว้นวรรคก่อนและหลังเครื่องหมายโคลอน และเว้นวรรคด้านหลังประเภทที่อยู่เบื้องหลัง ก่อนวงเล็บปีกกาเปิด
- ค่า enum สุดท้ายอาจไม่มีคอมมาเกิน
การประกาศแบบมีโครงสร้าง
ใช้กฎต่อไปนี้สำหรับการประกาศโครงสร้าง
- หากแชร์การประกาศ Struct กับแพ็กเกจอื่น ให้ใส่การประกาศ
ใน
types.hal
แทนการฝังภายในอินเทอร์เฟซ - เว้นวรรคหลังชื่อประเภทโครงสร้างก่อนวงเล็บปีกกาเปิด
- จัดชื่อช่อง (ไม่บังคับ) ตัวอย่าง
struct MyStruct {
vec<uint8_t> data;
int32_t someInt;
}
การประกาศอาร์เรย์
อย่าเว้นวรรคระหว่างรายการต่อไปนี้
- ประเภทองค์ประกอบและวงเล็บเหลี่ยมแบบเปิด
- วงเล็บเหลี่ยมเปิดและขนาดอาร์เรย์
- ขนาดอาร์เรย์และวงเล็บเหลี่ยมปิด
- วงเล็บเหลี่ยมปิดและวงเล็บเหลี่ยมเปิดถัดไป หากมีมากกว่า 1 ตัว มีมิติข้อมูลอยู่แล้ว
ตัวอย่าง
/* Good */
int32_t[5] array;
/* Good */
int32_t[5][6] multiDimArray;
/* Bad */
int32_t [ 5 ] [ 6 ] array;
เวกเตอร์
อย่าเว้นวรรคระหว่างรายการต่อไปนี้
vec
และวงเล็บมุมเปิด- วงเล็บมุมเปิดและประเภทองค์ประกอบ (ข้อยกเว้น: ประเภทองค์ประกอบยังเป็น
vec
) - ประเภทองค์ประกอบ และวงเล็บมุมปิด (ข้อยกเว้น: ประเภทองค์ประกอบยังเป็น
vec
)
ตัวอย่าง
/* Good */
vec<int32_t> array;
/* Good */
vec<vec<int32_t>> array;
/* Good */
vec< vec<int32_t> > array;
/* Bad */
vec < int32_t > array;
/* Bad */
vec < vec < int32_t > > array;