仅匹配某些类型的模板函数? [英] Template function that matches only certain types?
问题描述
我想定义一个函数模板:
I want to define a function template:
template<typename T>
void foo(T arg)
但我希望 T
只匹配某些类型.具体来说,T
应该从某个基类派生(可能通过多重继承).否则,此模板不应包含在重载集中.
But I want T
to match only certain types. Specifically, T
should derive (maybe through multiple inheritance) form a certain base class. Otherwise this template shouldn't be included in the overload set.
我该怎么做?
推荐答案
使用 SFINAE 和 <代码>std::is_base_of:
Use SFINAE with std::is_base_of
:
template <typename T,
typename = std::enable_if_t<
std::is_base_of<Foo, T>::value
>>
void foo(T arg);
如果T
继承自Foo
,那么它只会在重载集中包含foo
.请注意,这也包括模棱两可和不可访问的基础.如果您想要一个仅允许 T
从 Foo
继承公开和明确的解决方案,那么您可以而是使用 std::is_convertible
:
That will only include foo
in the overload set if T
inherits from Foo
. Note that this includes ambiguous and inaccessible bases as well. If you want a solution that only allows for T
s that inherit publicly and unambiguously from Foo
, then you can instead use std::is_convertible
:
template <typename T,
typename = std::enable_if_t<
std::is_convertible<T*, Foo*>::value
>>
void foo(T arg);
注意参数的颠倒.
无论您选择哪种形式,都可以为简洁起见使用别名:
Regardless of which form you pick, it can be aliased for brevity:
template <typename T>
using enable_if_foo = std::enable_if_t<std::is_base_of<Foo, T>::value>;
template <typename T,
typename = enable_if_foo<T>>
void foo(T arg);
这是有效的,因为 std::enable_if
有一个名为 type
的嵌套类型,当且仅当传入的布尔值为 true
.所以如果 std::is_base_of
是 true
,enable_if_t
被实例化为 void
,就好像我们写过:
This works because std::enable_if
has a nested type named type
if and only if the boolean passed in is true
. So if std::is_base_of<Foo, T>::value
is true
, enable_if_t
gets instantiated to void
, as if we had written:
template <typename T,
typename = void>
void foo(T arg);
但是,如果 T
不继承自 Foo
,那么类型特征将评估为 false
,并且 std::enable_if_t
是替换失败 - 没有 typename enable_if
.您可能会认为这是一个编译错误,但是 s替换 failure is not an e错误(sfinae).只是模板推导失败.因此,在这种情况下,效果是 foo
只是从可行的重载候选集中删除,与任何其他模板推导失败没有什么不同.
But, if T
does not inherit from Foo
, then the type trait will evaluate as false
, and std::enable_if_t<false>
is a substitution failure - there is no typename enable_if<false>::type
. You might expect this to a compile error, but substitution failure is not an error (sfinae). It's just a template deduction failure. So the effect is that foo<T>
is simply removed from the set of viable overload candidates in this case, no different from any other template deduction failure.
这篇关于仅匹配某些类型的模板函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!