下面是一段C++17的代碼:
//函數1:
template <typename... BufferTypes,
std::enable_if_t<std::conjunction<CanAppendBufferType<std::decay_t<BufferTypes>>...>::value> * = nullptr>
inline explicit FCompositeBuffer(BufferTypes&&... Buffers)?
{?
if constexpr (sizeof...(Buffers) > 0)
{
Segments.Reserve((GetBufferCount(Forward<BufferTypes>(Buffers)) + ...));
(AppendBuffers(Forward<BufferTypes>(Buffers)), ...);
Segments.RemoveAll(&FSharedBuffer::IsNull);
}
}
紅色字體表示語法上的整體。
1、 template <typename... BufferTypes, 表示聲明若干個類型名;
2、CanAppendBufferType< std::decay_t<BufferTypes> > 這是一個關于類型的調用,具體含義先忽略;
3、std::conjunction<CanAppendBufferType<std::decay_t<BufferTypes>>...>
將它看成此形式:?std::conjunction<? condition<BufferTypes>...? >
此時,紅色字體是一個整體,... 將會unpack(解壓)? condition<SomeArgs> 這個模式,并以逗號分割的參數形式,傳遞給?std::conjunction ,即等價于:
?std::conjunction<? condition<BT1>, condition<BT2>,?condition<BT3>??>
4、std::conjunction< a, b, c >::value??的意思是 a || b || c?的值,但是,它是模板元編程,也就是在“編譯時期”計算 a||b||c 的,不會影響運行時性能,且不能用 || 來代替,且a\b\c 都是編譯時確定值的變量,而非類型。
5、std::enable_if_t< some_value >? 其實是?std::enable_if_t< some_value , void > 的簡稱,且?std::enable_if_t 的定義是:
template <bool _Test, class _Ty = void> using enable_if_t = typename enable_if<_Test, _Ty>::type;
enable_if<the_value, the_type> ::type 的 意思是?
如果the_value是true,則定義為形式2,如果the_value是false,則定義為形式1 。
template <bool _Test, class _Ty = void> struct enable_if {}; // no member "type" when !_Test //形式1template <class _Ty> struct enable_if<true, _Ty> { // type is _Ty for _Test //形式2using type = _Ty; };
此時根據 C++17模板元編程的原則?“SFINAE(Substitution Failure Is Not An Error,替換失敗并非錯誤)” ,如果找不到 ::type? ,那么就忽略掉模板函數,而非報錯。
同時,enable_if_t 是?typename enable_if<_Test, _Ty>::type; 的昵稱。因此?std::enable_if_t< some_value >? 的意思是,如果有?some_value 的值,那么此處就以 void 來定義,如果沒有,那么就當該函數 (函數1)不存在。
6、template <typename... BufferTypes,??? ?some_type??* = nullptr>??
由于5的論述,我們知道,some_type 只可能是 void ,否則把該模板函數(函數1)當做不存在。那么上述表達等價于:
template <typename... BufferTypes, ? void * = nullptr>
不妨補充其匿名的名稱為 secretboy ,如下
template <typename... BufferTypes,? ?( void * ) secretboy = nullptr>
也就是說,逗號的后面,是一個值(而不是類型),且該值沒有名字,它不會被函數體用到,那么它無關緊要。既然無關緊要,為啥還需要它呢?因為要讓它的計算起到 SFINAE 的作用。所以,如果5合法,那么 它等價于?
template <typename... BufferTypes >
如果5不合法,那么忽略函數1的存在。
7、? if constexpr (sizeof...(Buffers) > 0)
表示如果 Buffers 有真實的數量,那么 就需要編譯下面的代碼,否則不用編譯。
8、(GetBufferCount(Forward<BufferTypes>(Buffers)) + ...)?
我們把它簡化為這個形式: (func(BufferTypes) + ... )
其中的 + ,在語法上還可以是 -? (減號)? || (或者),甚至是 , (逗號) 。
也就是說,函數調用后的 參數包 ,可以展開,等價于:
func(BT1) + func(BT2) + ...? ? (式子8)
并且請注意,? args + ... 的展開等價于 a + ( b + ( c + d ) ) ,所以嚴格來說,式子8不夠嚴謹,應該等價于:
func(BT1) + ( func(BT2) + ( ... ) )? ? (式子9)