这更像是一个 C++ 标准问题。 考虑以下代码:
template <typename T>
class has_Data
{
typedef char one;
typedef long two;
template <typename C> static one test( typeof(&C::Data) ) ;
template <typename C> static two test(...);
public:
enum { value = sizeof(test<T>(0)) == sizeof(char) };
};
class MyClass {
private:
struct Data {
};
};
void function(bool val = has_Data<MyClass>::value) {}
以上代码适用于 gcc (GCC) 4.4.3
但是 clang 版本 3.3 (2545b1d99942080bac4a74cda92c620123d0d6e9) (2ff97832e593926ea8dbdd5fc5bcf367475638a9)
它给出了这个错误:
test_private_data.cpp:7:54: error: 'Data' is a private member of 'MyClass'
template <typename C> static one test( typeof(&C::Data) ) ;
^
/devshared/home/rhanda/test_private_data.cpp:7:37: note: while substituting explicitly-specified template arguments into function template 'test'
template <typename C> static one test( typeof(&C::Data) ) ;
^
/devshared/home/rhanda/test_private_data.cpp:21:26: note: in instantiation of template class 'has_Data<MyClass>' requested here
void function(bool val = has_Data<MyClass>::value) {}
^
1 error generated.
哪个是对的?
从标准文档 ( n3485 ) 中,我发现了一个似乎比 gcc 更符合 clang 的声明。
Access control is applied uniformly to all names, whether the names are referred to from declarations or expressions.
最佳答案
我认为 GCC 是正确的。
首先要注意的是,没有非 friend
代码应该能够积极报告给定私有(private)成员的存在。所以如果那是你想做的,你必须修改你的设计。一个类可以对其私有(private)成员做任何事情,其他代码( friend 除外)应该无法知道它。这是设计使然。
但是,有 SFINAE原则:替换失败不是错误。自 MyClass::Data
是私有(private)的,has_Data
中的代码在我看来,应该像没有C::Data
一样行事。完全是成员(member)。因此第一个函数会导致替换失败,它会被默默地忽略,而第二个函数是使用的那个。添加更多代码,我的 GCC 4.7.2 可以毫无问题地编译它并使用 has_Data<MyClass>::value
评估为 false
.在我看来正确的 SFINAE。
试图用 the document you referred to 的引文来支持这一观点,我在第 14.8.2 节第 8 段中找到以下内容:
Note: Access checking is done as part of the substitution process.
这是标准中的非规范性注释,但对我来说似乎是一个非常可读和清楚的指示,表明 SFINAE 实际上应该适用于这种情况,就像 GCC 处理它的方式一样。
编辑作为@hvd在 a comment 中指出,以上仅适用于 C++11。在标准的旧版本中,情况过去有所不同。 Issue 1170: Access checking during template argument deduction有关于该更改的详细信息。
GCC 不会用 -std=c++03
编译这段代码或 -std=c++11
因为 typeof
是一个 GNU 扩展。事实-std=gnu++03
仍然编译代码可能被认为是不合适的,但由于前进的方向是使用 C++11 语义,我不会费心就此提交报告。
关于c++ - 使用元编程的私有(private)成员存在性测试,GCC vs clang,哪个是对的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16206626/