成员功能模板专业化是否可以具有与主模板不同的访问级别
May a member function template specialization have a different access level than the main template?
我在回答一个关于删除函数的问题时提到,成员函数模板不能在类范围内专门化。这让我怀疑成员函数模板专业化是否有可能拥有与主模板不同的访问级别。在下面的代码中,我试图拥有一个公共成员函数模板的私有专业化:
#include <iostream>
class Foo {
public:
template<typename T>
void func(T) { std::cout << "Publicn"; }
private:
template<>
void func<char>(char) { std::cout << "Privaten"; }
friend int main();
};
int main()
{
Foo f;
f.func(10);
f.func('a');
}
使用最新的MSVC,它编译、运行并产生预期的输出:
Public
Private
对于g++4.8和Clang 3.2,该代码被拒绝。Clang这样说:
error: explicit specialization of 'func' in class scope
void func<char>(char) { std::cout << "Privaten"; }
^
假设g++和Clang使用C++11的14.7.3/2作为他们行为的基础,但我认为可能有一点回旋余地,因为3.3.6/3说全局范围是一个命名空间,全局命名空间(间接)包含了模板专用化。
我的问题不是关于标准的这些部分,也不是关于这些编译器的任何行为,而是关于成员函数模板是否可能具有与通用模板不同的访问级别的专门化。例如,是否可以有一个公共成员函数模板和该模板的私有专用化?
我们总是可以手动完成。
一些随机的SFINAE机器:
#include <iostream>
#include <utility>
#include <type_traits>
template<typename T> constexpr bool IsInt() { return std::is_same<T,int>::value; }
template<std::size_t>
struct SecretEnum {
enum class hidden {};
};
template<bool b, int i=1> using EnableIf = typename std::enable_if<b,typename SecretEnum<i>::hidden>::type;
class Foo {
public:
template<typename T, EnableIf< !IsInt<T>(), 1 >...>
void func(T) { std::cout << "Publicn"; }
private:
template<typename T, EnableIf< IsInt<T>(), 2 >...>
void func(T) { std::cout << "Private with intn"; }
friend int main();
};
int main()
{
Foo f;
f.func(10);
f.func('a');
}
现在这个技巧不适用于clang,因为我上次检查时是如何进行SFINAE和方法区分的。但这可以用其他类似的技巧来代替(比如第二个参数中基于指针的默认参数——用EnableIf< IsInt<T>(), 2 >* = nullptr
或类似的clang来代替EnableIf< IsInt<T>(), 2 >...
。我只是觉得它不那么吸引人。)
那么,上面发生了什么?我有两个不同的func
过载。两者都是模板函数,其中一个参数是T
,还有一个秘密枚举包,其类型在T
分别与IsInt<T>()
或!IsInt<T>()
测试匹配时和仅当CCD_5匹配时有效。在这两种情况下,包的类型不同(一种是SecretEnum<2>::hidden
,另一种是CCD _9),因此它们的签名差异很大,足以满足大多数C++11编译器的要求(clang认为它们在上次检查时是相同的,产生了错误,我认为clang错了)。
当您调用func<blah>
时,它会检查两个func
中的哪一个(如果有的话)是合适的。由于它们的条件是完全相反的,所以只有其中一个是合适的。
实际上,我们正在进行手工专业化。
在C++1y中,如果恒星正确对齐,并且技术报告中的概念lite允许这样做,我们可能能够template<IsInt T>
和template<IsNotInt T>
。
- 固有构造函数的字符和访问级别
- 使用级别访问的 C++ 类组织
- 任务计划程序:设置运行级别时拒绝访问
- 从特定专业化继承时可访问的模板基类?
- 如何访问相同特征C 的不同性状专业化
- 如何从C或C 语言级别安全访问内存映射的硬件寄存器
- 访问说明符不会更改可访问性级别.这是什么意思
- 包访问级别
- 忽略了部分功能专业化中价值类型的最高级别const预选赛
- 成员功能模板专业化是否可以具有与主模板不同的访问级别
- 如何调试C++非托管代码中的较低级别文件访问异常/崩溃
- 警告级别4中的不可访问代码警告
- 为什么使用声明生成的构造函数具有与基类相同的访问级别?
- 多个级别的专用和公共异常访问
- 指向成员的指针可能绕过成员的访问级别
- 对继承和访问级别的困惑
- 为什么我们不能在继承中更改基类中函数的访问级别?
- c++类访问级别
- 访问级别
- C++11提供了一种静态测试方法访问级别的方法