"used as non-type template parameter" 是否使函数模板隐式实例化?

Does "used as non-type template parameter" make a function template implicitly instantiated?

我想编写一个 class 模板 M 接受不完整类型 C 作为模板参数。 但我也希望 C 在最终定义时具有一些特征。

这个码有保证吗

template <auto> struct Dummy {};

template <typename C>
void check()
{
    static_assert(std::is_trivial_v<C>);
}

template <typename C>
struct M : Dummy<&check<C>>
{
    //static_assert(std::is_trivial_v<C>);//error: incomplete type
    C * p;
};

struct Test;
M<Test> m;

int main()
{
    return 0;
}

#if defined(FLAG)
struct Test {};
#else
struct Test { std::string non_trivial_member; };
#endif

From a n4713,

实例化点 [temp.point] (17.7.4.1/8)

A specialization for a function template, a member function template, or of a member function or static data member of a class template may have multiple points of instantiations within a translation unit, and in addition to the points of instantiation described above, for any such specialization that has a point of instantiation within the translation unit, the end of the translation unit is also considered a point of instantiation. A specialization for a class template has at most one point of instantiation within a translation unit. A specialization for any template may have points of instantiation in multiple translation units. If two different points of instantiation give a template specialization different meanings according to the one-definition rule (6.2), the program is ill-formed, no diagnostic required.

首先,请注意,主要模板是 paa0ssed 参数,是标准语言的专业化。根据我的经验,C++ 程序员使用它的方式与标准不同。

其次,check<Test>在你的程序中有两个实例化点;曾经在

M<Test> m;

并在翻译单元末尾出现一次。

M<Test> mcheck<Test>的含义与翻译单元末尾check<Test>的含义不同。在一个地方,Test 是不完整的,在另一个地方是完整的。 check<Test> 的正文肯定有不同的含义。

所以你的程序格式错误,不需要诊断。在您的情况下,格式错误的程序恰好可以执行您想要的操作,但它可以(在标准下)编译成任何东西,或者无法编译。

我怀疑这条规则背后的原因是让编译器可以自由地立即实例化 check 或将其推迟到以后实例化。您不能依赖它实际执行 check.

主体实例化的两个点中的哪一个