【问题标题】:Explicit template instantiation using alias?使用别名的显式模板实例化?
【发布时间】:2025-12-25 03:20:22
【问题描述】:

Header.h

template <int>
class FiniteElement {
public:
    int GetDOF();
};

using FiniteElement2D = FiniteElement<3>;
using FiniteElement3D = FiniteElement<6>;

Source.cpp

#include "Header.h"

//template class FiniteElement<3>;
//template class FiniteElement<6>;
template FiniteElement2D;  // Using alias for explicit template instantiation !!!
template FiniteElement3D;

template <int DOF>
int FiniteElement<DOF>::GetDOF() {
    return DOF;
}

Main.cpp

#include "Header.h"
#include <iostream>

int main() {
    FiniteElement3D Elem;
    std::cout << Elem.GetDOF();
    return 0;
}

令我惊讶的是,上面的程序编译并链接到 Visual Studio 2015 Update 3。我喜欢允许将别名用于显式模板实例化的想法,但它似乎不适用于 gcc 或 clang。

它是即将发布的标准的特性还是 VS 的特定特性?

【问题讨论】:

  • 这无法与当前的 Clang/C2(2016 年 7 月)链接,但仍与今天的每日构建(v19.10.24606)链接。请file a bug report 并在此处发布链接。
  • @GuillaumeRacicot 回想起来很容易称其为“愚蠢”,但现在很明显这是一个糟糕的设计决策。 blogs.msdn.microsoft.com/vcblog/2015/09/25/… 是的,VS 仍然不符合标准,是的,所有其他主要编译器现在暂时完全符合 C++14。但是你必须赞扬他们拥有并(慢慢地)朝着正确的方向前进:blogs.msdn.microsoft.com/vcblog/2016/06/07/…。他们(以及我们作为用户)正在为很久以前犯的错误付出代价 - 当时看起来是正确的
  • @bolov 是的,你是对的。我想我今天有很多 VS 错误...
  • 对于 GCC,您可以通过说 template class FiniteElement2D::FiniteElement(注入的类名)来解决它。 Clang 也不喜欢这样 :)
  • @Barry 我确定它是有效的。见*.com/a/13332744/34509

标签: c++ templates visual-studio-2015 c++17


【解决方案1】:

答案是在 cmets 中给出的,但有点伪装,所以我将在这里展开。

MSVC 编译器在这种情况下的工作方式几乎就像在程序代码中进行文本替换一样。它基本上将 FiniteElement2D 的所有文本替换为 FiniteElement&lt;3&gt; - 这样显式实例化对您来说很好。

另一方面,其他编译器为typedef 构建适当的抽象语法树,因此别名的使用不会扩展到显式模板实例化。

顺便说一句,我不确定您希望从您的语法中获得什么样的好处。

【讨论】:

  • 我只是碰巧在我的代码中使用了与 OP 相同的语法。在msvc中编译成功后也遇到了gcc编译问题。好处是,它只需要在一个地方进行更改(即 in using 声明),它将传播到显式模板实例化。如果没有这种方法,您需要在 2 个地方进行更改。在 1 处更改几乎总是比在 2 处更改更干净。
  • @MarcinK。在使用 mixins 时,IMO 还可以极大地提高可读性(并降低做错的风险),甚至在使用 CRTP 时更糟。