6.3 使用enable_if<>禁用模板
6。3 使用enable_if<>禁用模板 Disable Templates with enable_if
C++11以後,C++標準庫提供幫助類模板
std::enable_if<>
用於在特定編譯條件下忽略函式模板,比如:
template
<
typename
T
>
typename
std
::
enable_if
<
(
sizeof
(
T
)
>
4
)
>::
type
foo
()
{
}
如果
sizeof(T)>4
為
false
,那麼
foo<>()
的定義就會被忽略。如果
sizeof(T)>4
為true,函式模板例項拓展為:
void
foo
()
{}
std::enable_if<>
是個型別特性,它評價給定的編譯時表示式作為第一個模板引數:
如果表示式為true,它的型別成員
type
推匯出一個型別:
如果沒有傳遞第二個模板引數,該型別為void
否則,該型別為傳入的第二個模板引數
如果表示式為false,它的成員型別是未定義的。由於SFINAE(substitution failure is not an error) 模板特性,有
std::enable_if<>
表示式的函式模板將被忽略。
C++14以後提供了別名模板
std::enable_if_t<>
允許跳過
typename
和
::type
。因此C++14以後可以這麼寫:
template
<
typename
T
>
std
::
enable_if_t
<
(
sizeof
(
T
)
>
4
)
>
foo
()
{}
也可以將第二個模板引數傳給
std::enable_if<>
或者
std::enable_if_t<>
:
template
<
typename
T
>
std
::
enable_if_t
<
(
sizeof
(
T
)
>
4
),
T
>
foo
()
{
return
T
();
}
因此,如果
MyType
是傳入的實際型別或者推導為T,並且它的size大於4,就等效於
MyType
foo
();
enable_if
表示式放在宣告中間顯得相當笨拙。由於這個原因,常用的方式是使用一個額外的的函式模板實參,將
std::enable_if<>
作為該實參的預設值:
template
<
typename
T
,
typename
=
std
::
enable_if_t
<
(
size
(
T
)
>
4
)
>>
void
foo
()
{}
如果
sizeof(T)>4
,那麼它將拓展為:
template
<
typename
T
,
typename
=
void
>
void
foo
()
{}
如果這還是太笨拙,可以使用別名模板:
template
<
typename
T
>
using
EnableIfSizeGreater4
=
std
::
enable_if_t
<
(
sizeof
(
T
)
>
4
)
>
;
template
<
typename
T
,
typename
=
EnableIfSizeGreater4
<
T
>>
void
foo
()
{}