Dan*_*our 3 c++ templates template-meta-programming
给定一个“正常”模板:
template<typename> struct Normal;
Run Code Online (Sandbox Code Playgroud)
和别名模板:
template<typename>
using Alias = void;
Run Code Online (Sandbox Code Playgroud)
当作为模板模板参数给出时,我如何区分这两者?
因此,理想情况下我希望编译以下内容:
int main() {
static_assert( is_alias_template<Alias>::value, "");
static_assert(! is_alias_template<Normal>::value, "");
}
Run Code Online (Sandbox Code Playgroud)
一种可能的方法是利用:
在推导模板模板形参时,永远不会通过模板实参推导来推导出别名模板。
因此,具有像这样的类型特征
template<
typename T,
template<typename...> class Template
>
struct instantiated_from
: std::false_type {};
template<
template<typename...> class Template,
typename... Arguments
>
struct instantiated_from<Template<Arguments...>, Template>
: std::true_type {};
Run Code Online (Sandbox Code Playgroud)
我们可以确定,当我们Alias<int>
作为第一个模板参数和Alias
第二个模板参数传递时,编译器不会选择专门化。这立即给我们带来了:
template<
template<typename...> class Template,
typename... Args
>
struct is_alias_template
: std::integral_constant<
bool,
! instantiated_from<Template<Args...>, Template>::value
>
{};
Run Code Online (Sandbox Code Playgroud)
有了这个,我们可以 -给定一些合适的模板参数- 检测模板是否是别名模板:
int main() {
static_assert( is_alias_template<Alias, int>::value, "");
static_assert(! is_alias_template<Normal, int>::value, "");
static_assert( is_alias_template<Alias, Alias<int>>::value, "");
static_assert( is_alias_template<Alias, Normal<int>>::value, "");
static_assert(! is_alias_template<Normal, Alias<int>>::value, "");
static_assert(! is_alias_template<Normal, Normal<int>>::value, "");
}
Run Code Online (Sandbox Code Playgroud)
这里的主要缺点当然是需要知道一组合适的模板参数。例如,仅猜测(或使用int
)对于具有固定数量 (>1) 模板参数的模板是行不通的。
此外,这不适用于具有非类型(或模板)模板参数的(别名或非别名)模板。