如何检测模板是否为别名模板?(涉及IT技术)

3

给出一个“普通”的模板:

template<typename> struct Normal;

以及一个别名模板:

template<typename>
using Alias = void;

当作为模板参数给出时,我该如何区分这两个?

因此,理想情况下,我希望以下内容能够编译:

int main() {
  static_assert(  is_alias_template<Alias>::value, "");
  static_assert(! is_alias_template<Normal>::value, "");
}
1个回答

5

一种可能的方法是利用以下特点:

当推导模板模板参数时,别名模板永远不会被模板参数推导所推导。

http://en.cppreference.com/w/cpp/language/type_alias

因此,使用这样的类型特征:

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 {};

我们可以确定,当我们将 Alias<int> 作为第一个模板参数,Alias 作为第二个时,编译器不会选择该特化。这立即给我们带来了以下结果:
template<
  template<typename...> class Template,
  typename... Args
  >
struct is_alias_template
  : std::integral_constant<
      bool,
      ! instantiated_from<Template<Args...>, Template>::value
      >
{};

通过这个方法,我们可以- 在提供一些适当的模板参数后 - 检测一个模板是否是别名模板:

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, "");
}

这里的主要缺点是必须知道一组适当的模板参数。仅猜测(或使用 int)不适用于具有固定数量(>1)的模板参数的模板,例如。
此外,这无法与具有非类型(或模板)模板参数的(别名或非别名)模板配合使用。

如果 template<class T> using Alias = Normal<T>,那么这种方法适用于 msvc 和 clang,但不适用于 gcc。你知道还有其他可能性吗? - undefined
@klaustriendl你能详细说明一下吗?或者最好能给出一个(完整但最简洁的)例子,说明上述代码无法正常工作的情况? - undefined
1
当别名模板具有与类模板相同的模板参数时,gcc会确定instantiated_from<T>::value==true。它需要与OP的问题中的template<class T> using Alias = void不同,或者使用可变模板参数template<class... T> using Alias = Normal<T...>或者使用虚拟参数template<class T, class Dummy = void> using Aliase = Normal<T>。请参见godbolt - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接