在专业化之前使用模板吗? [英] Using a template before it's specialized?

查看:60
本文介绍了在专业化之前使用模板吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现您可以在之后专门化模板,如果您使用包装模板来使用它的话.简单的例子:

I found out that you can specialize a template after it's first use if you use it using a wrapper template. Simple example:

#include <iostream>

template<typename T>
const char* templateImpl();

template<typename T>
const char* templateGetter() { return templateImpl<T>(); }

struct S{};

int main(){ std::cout << templateGetter<S>() << std::endl; return 0; }

template<>
const char* templateImpl<S>(){ return "S"; }

这适用于所有编译器-我并不惊讶MSVC对其进行编译,因为它以不同的方式处理模板,但是GCC和clang也允许它.我认为该标准要求专门化必须在首次使用之前进行,在这种情况下,这意味着要在主要应用程序之前进行,并期望他们报告错误.

This works with every compiler - I'm not surprised MSVC compiles it since it handles templates differently, but GCC and clang allow it too. I thought the standard required the specialization to occur before the first use, which in this case would mean before main and expected them to report an error.

我错过了什么吗,此代码标准兼容吗?

Did I miss something, is this code standard compliant?

为澄清起见,如果我将 templateGetter< S> 更改为main中的 templateImpl< S> ,程序将不会编译出我希望从中得到的错误消息也是:

To clarify, if I change templateGetter<S> to templateImpl<S> in main, the program won't compile with the error message I would expect from this too:

main.cpp:14:29:错误:'const char * templateImpl()的特殊化实例化后[with T = S]'

main.cpp:14:29: error: specialization of 'const char* templateImpl() [with T = S]' after instantiation

推荐答案

您很幸运.这是格式错误的NDR.

You got (un)lucky. This is ill-formed NDR.

[temp.expl.spec]/6-7 :

6 如果模板,成员模板或类模板的成员是显式专业化然后应声明专业化在第一次使用该专业知识之前,会导致隐式实例化发生在每个翻译单元中会发生什么用途;无需诊断.[...]

6 If a template, a member template or a member of a class template is explicitly specialized then that specialization shall be declared before the first use of that specialization that would cause an implicit instantiation to take place, in every translation unit in which such a use occurs; no diagnostic is required. [...]

7 函数模板,类模板,变量模板,类模板的成员函数,类模板的静态数据成员,类模板的成员类,类的成员枚举的显式专门化声明的位置模板,类模板的成员类模板,类模板的成员函数模板,类模板的静态数据成员模板,类模板的成员模板的成员函数,非模板类的成员模板的成员函数,非模板类的静态数据成员模板-template类,类模板的成员类的成员函数模板等,以及类模板,变量模板,非模板类的成员类模板,非模板类的静态数据成员模板,类模板等的成员类模板会根据程序的相对位置影响程序是否格式正确上面和下面指定的在翻译单元中的显式专门化声明及其实例化点.编写专长时,请注意其位置;或对其进行编译将是一次试探,以点燃其自焚之情.

7 The placement of explicit specialization declarations for function templates, class templates, variable templates, member functions of class templates, static data members of class templates, member classes of class templates, member enumerations of class templates, member class templates of class templates, member function templates of class templates, static data member templates of class templates, member functions of member templates of class templates, member functions of member templates of non-template classes, static data member templates of non-template classes, member function templates of member classes of class templates, etc., and the placement of partial specialization declarations of class templates, variable templates, member class templates of non-template classes, static data member templates of non-template classes, member class templates of class templates, etc., can affect whether a program is well-formed according to the relative positioning of the explicit specialization declarations and their points of instantiation in the translation unit as specified above and below. When writing a specialization, be careful about its location; or to make it compile will be such a trial as to kindle its self-immolation.

p7在这里并不是真的有用,但是我不能拒绝引用它:)

实例化 templateGetter< S> 导致 templateImpl< S> 的声明的隐式实例化.您没有看到代码有错误,因为许多实现都希望将模板实例化推迟到翻译单元的尽头,这是一种允许的实现技术.(我不会在这里引用标准术语,但是您会发现功能模板的专业化在翻译单元的末尾有一个额外的实例化点.)

Instantiating templateGetter<S> causes the implicit instantiation of a declaration of templateImpl<S>. You didn't see an error with your code because many implementations like to defer template instantiations until the end of the translation unit when possible, which is a permitted implementation technique. (I'm not going to quote the standardese here, but you'll find that function template specializations have an extra point of instantiation at the end of the translation unit.)

赋予 templateGetter 推导的返回类型将强制其主体的早期实例化:

Giving templateGetter a deduced return type will force early instantiation of its body:

template<typename T>
auto templateGetter() { return templateImpl<T>(); }

:

+ g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp
main.cpp:14:29: error: specialization of 'const char* templateImpl() [with T = S]' after instantiation
 const char* templateImpl<S>(){ return "S"; }
                             ^
+ clang++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp
main.cpp:14:13: error: explicit specialization of 'templateImpl<S>' after instantiation
const char* templateImpl<S>(){ return "S"; }
            ^
main.cpp:7:32: note: implicit instantiation first required here
auto templateGetter() { return templateImpl<T>(); }
                               ^
1 error generated.

这篇关于在专业化之前使用模板吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆