模板特化的 using 声明是否总是导致其隐式实例化?

问题描述 投票:0回答:1

我了解以下行为是违法的:


template<typename T>
struct will_get_explicitly_specialized {
    using type = void;
};

template<typename T>
struct ordinary_template {
    using type = typename will_get_explicitly_specialized<T>::type;
};

ordinary_template<int> x;

template<>
struct will_get_explicitly_specialized<int> {
     using type = int;
};

这将(希望如此,因为我相信这不是必需的)生成如下错误:

<source>:16:8: error: specialization of 'will_get_explicitly_specialized<int>' after instantiation
   16 | struct will_get_explicitly_specialized<int> {
      |        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:16:8: error: redefinition of 'struct will_get_explicitly_specialized<int>'
<source>:4:8: note: previous definition of 'struct will_get_explicitly_specialized<int>'
    4 | struct will_get_explicitly_specialized {
      |        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Compiler returned: 1

这符合我的理解,即

will_get_explicitly_specialized
的所有显式特化都需要出现在
will_get_explicitly_specialized
的任何隐式实例化之前,并且
ordinary_template<int> x
的声明必然会导致
ordinary_template<int>
的实例化,而这又似乎需要隐式实例化由于
will_get_explicitly_specialized<int>
声明,
using type = 

有趣的是,代码中该位置的顶级

using
语句不会引发诊断(在相同环境中):

template<typename T>
struct will_get_explicitly_specialized {
    using type = void;
};

template<typename T>
struct ordinary_template {
    using type = typename will_get_explicitly_specialized<T>::type;
};

using ot_int = ordinary_template<int>;

template<>
struct will_get_explicitly_specialized<int> {
     using type = int;
};

ot_int x;

我想知道这是否仍然是非法的(但也许没有发出诊断并且不需要诊断),或者这种

using
语句是否与
ordinary_template
中的语句有所不同,因此它不算数导致
will_get_explicitly_specialized
的隐式实例化。

无论哪种情况,什么语言可以清楚地表明

using
语句中模板的特化是否/何时导致隐式实例化?

直觉上感觉应该可以在所有专业化之前说

using ot_int = ordinary_template<int>
,因为直到你以某种方式实际使用
ot_int
之前,没有任何事情真正发生,以至于
ordinary_template<int>
需要存在。但当然,仅仅因为感觉是这样,并不代表它就是真的!

c++ templates language-lawyer
1个回答
0
投票

这将(希望如此,因为我相信这不是必需的)生成如下错误:

从技术上讲,第一个程序是根据 [temp.expl.spec]/7 的 IFNDR(格式错误,无需诊断),因为没有声明可从

will_get_explicitly_specialized<int>
访问
ordinary_template<int> x;
的显式专业化,但是这会导致相同专业化的隐式实例化。

因此从技术上讲不需要编译器来诊断问题。该程序对编译器没有任何要求。


简单地使用 template-id 命名专业化不会导致它被隐式实例化。仅当类类型在使用时要求完整或其完整性会影响程序语义时,类模板特化才会隐式实例化。

在变量的定义中,例如

ordinary_template<int> x;

ot_int x;

变量的类型必须始终完整。这意味着在这两种情况下

ordinary_template<int>
必须在此时隐式实例化(如果它尚未事先实例化)。

但是,简单地声明类型别名并不要求类型完整,并且如果类型不完整,声明也不具有任何不同的语义。

因此,简单地为类模板特化添加别名永远不会导致它被隐式实例化。因此,您的第二个程序不会违反上述规则,并且格式良好,具有定义的行为(除了缺少

main
之外)。根据显式专业化的要求,
ot_int::type
将是
int

© www.soinside.com 2019 - 2024. All rights reserved.