我碰巧发现可以使用using指令直接在封闭类之外访问嵌套的私有模板类:
class wrapper
{
private:
template <typename T>
class __tklass {};
class __klass {};
};
template <typename T>
using tklass = wrapper::__tklass<T>; // Expected error but compiles OK
// using klass = wrapper::__klass; // "Error: __klass is private"
int main()
{
tklass<int> v1; // Expected error but compiles OK
// wrapper::__tklass<int> v3; // "Error: __tklass is private"
// wrapper::__klass v4; // "Error: __klass is private"
}
Run Code Online (Sandbox Code Playgroud)
标记为"错误:__ xxxx为私有"的行在取消注释时正确报告错误.但是tklass编译的行没有编译器的任何抱怨.
那么,为什么编译器标记tklass为错误,尽管wrapper::__tklass它是私有的?是否有标准允许的任何机会?如果是这样,那不会被认为是严重的访问违规行为吗?
我试过gcc-4.9.2,clang-3.5.0和visual studio 2013 …
template <int * ip> struct test {};
struct q {
static int a;
int b;
constexpr q(int b_) : b(b_) {}
};
int i;
constexpr q q0(2);
int main()
{
constexpr test<&i> t1; // Works fine
constexpr test<&q::a> t2; // Works
constexpr test<&q0.b> t3; // Does not work; address of non-static member?
return 0;
}
Run Code Online (Sandbox Code Playgroud)
尽管&q0.b在编译期间已知模板参数,但上述代码中的t3声明仍然失败.一些谷歌搜索显示标准不允许这样做(第14.3.2节):
[注意:数组元素的地址和非静态类成员的名称或地址是不可接受的模板参数.
X <&m.m> x4; //错误:非静态元素的地址
那么,尽管全局变量的非静态成员的地址在编译时是唯一的以及已知的,但为什么这个标准明确禁止这一点呢?
当我这样做时,编译器不会抱怨;-)
// Myfile.h
#include <iostream>
#include <vector>
namespace std
{
template<> class vector<int>
{
public:
vector ()
{
std::cout << "Happy Halloween !!!\n";
}
};
}
Run Code Online (Sandbox Code Playgroud)
有没有办法防止类/函数模板的这种不合需要的专业化?
我只是用std ::作为例子.我正在寻找的是一种防止这种情况发生在任何模板类中的方法.
我一直在阅读将在C++ 14/17中引入的概念.根据我的理解,我们定义并使用这样的概念:
// Define the concept (from wikipedia)
auto concept less_comparable<typename T> {
bool operator<(T);
}
// A class which implements the requirements of less_comparable,
// with T=`const string &`
class mystring
{
bool operator < (const mystring & str) {
// ...
}
};
// Now, a class that requires less_comparable
template <less_comparable T>
class my_sorted_vector
{
// ...
};
// And use my_sorted_vector
my_sorted_vector<int> v1; // should be fine
my_sorted_vector<mystring> v2; // same
my_sorted_vector<struct sockaddr> v3; // must …Run Code Online (Sandbox Code Playgroud)