简体   繁体   English

SFINAE可以检测到私人访问违规吗?

[英]Can SFINAE detect private access violations?

I wonder whether if i test for some member of a class and the member is private what will sfinae respond? 我想知道如果我测试一个班级的某个成员并且该成员是私人的,那么sfinae会做出什么反应? Will it error out hard or will it say ok or will it error out in the sfinae way? 它是否会出错或者说是好的还是会以错误的方式出错?

Yes. 是。

EDIT: C++11 Standard quote from §14.8.2 [temp.deduct] 编辑: C ++ 11标准引自§14.8.2[temp.deduct]

8/ If a substitution results in an invalid type or expression, type deduction fails. 8 /如果替换导致无效的类型或表达式,则类型推导失败。 An invalid type or expression is one that would be ill-formed if written using the substituted arguments. 如果使用替换参数写入,则无效的类型或表达式将是格式错误的。 [ Note: Access checking is done as part of the substitution process. [注意:访问检查是作为替换过程的一部分完成的。 —end note ] - 尾注]

This suggests to me that private can trigger an SFINAE error. 这告诉我private可以触发SFINAE错误。 Reading on: 阅读:

Only invalid types and expressions in the immediate context of the function type and its template parameter types can result in a deduction failure. 只有函数类型的直接上下文中的无效类型和表达式及其模板参数类型才会导致演绎失败。 [ Note: The evaluation of the substituted types and expressions can result in side effects such as the instantiation of class template specializations and/or function template specializations, the generation of implicitly-defined functions, etc. Such side effects are not in the “immediate context” and can result in the program being ill-formed.—end note ] [注意:对替换类型和表达式的评估可能会导致副作用,例如类模板特化和/或函数模板特化的实例化,隐式定义函数的生成等。这些副作用不在“立即上下文“并且可能导致程序格式不正确.-最后说明]

The "immediate context" is not so clear to me... but it does not contradict my point :) “直接背景”对我来说并不是那么清楚......但它与我的观点并不矛盾:)

end of EDIT 编辑结束

So it seems to me that it will error out in an SFINAE way, this is further confirmed by this excerpt from Clang: 所以在我看来它会以SFINAE的方式出错,这一点从Clang的这段摘录中得到进一步证实:

// clang/Basic/DiagnosticIDs.h:185-209

  /// \brief Enumeration describing how the the emission of a diagnostic should
  /// be treated when it occurs during C++ template argument deduction.
  enum SFINAEResponse {
    /// \brief The diagnostic should not be reported, but it should cause
    /// template argument deduction to fail.
    ///
    /// The vast majority of errors that occur during template argument
    /// deduction fall into this category.
    SFINAE_SubstitutionFailure,

    /// \brief The diagnostic should be suppressed entirely.
    ///
    /// Warnings generally fall into this category.
    SFINAE_Suppress,

    /// \brief The diagnostic should be reported.
    ///
    /// The diagnostic should be reported. Various fatal errors (e.g.,
    /// template instantiation depth exceeded) fall into this category.
    SFINAE_Report,

    /// \brief The diagnostic is an access-control diagnostic, which will be
    /// substitution failures in some contexts and reported in others.
    SFINAE_AccessControl
  };

There are special cases with regard to Access Control in the case of SFINAE. 在SFINAE的情况下,存在关于访问控制的特殊情况。

No. I am on the road and don't have a standard to quote with me, but sfinae takes places in the phase of compilation where the compiler checks if the name exists at all, and in a later phase access control takes place. 不,我在旅途中并没有引用标准的标准,但是在编译阶段,编译器会检查名称是否存在,并且在稍后阶段进行访问控制。

This is similar to overload resolution, where all names are considered, and a match that is private is better, but won't compile, although there is another match that would be "ok" but not private. 这类似于重载决策,其中考虑了所有名称,并且私有匹配更好,但不会编译,尽管有另一个匹配“ok”但不是私有。

Addition: 加成:

Core issue 1170 says: 核心问题1170说:

1170 Access checking during template argument deduction 1170模板参数扣除期间的访问检查
Section: 14.8.2 [temp.deduct] 条:14.8.2 [temp.deduct]
Status: FDIS Submitter: Adamczyk Date: 2010-08-03 状态:FDIS提交者:Adamczyk日期:2010-08-03

[Voted into the WP at the March, 2011 meeting.] [2011年3月会议上投票支持WP。]

According to 14.8.2 [temp.deduct] paragraph 8, 根据14.8.2 [temp.deduct]第8段,

Access checking is not done as part of the substitution process. 访问检查不是替换过程的一部分。 Consequently, when deduction succeeds, an access error could still result when the function is instantiated. 因此,当推导成功时,在实例化函数时仍可能导致访问错误。

This mimics the way access checking is done in overload resolution. 这模仿了在重载决策中完成访问检查的方式。 However, experience has shown that this exemption of access errors from deduction failure significantly complicates the Standard library, so this rule should be changed. 但是,经验表明,从扣减失败中获取访问错误会使标准库显着复杂化,因此应更改此规则。

Proposed resolution (January, 2011): 拟议决议(2011年1月):

Change 14.8.2 [temp.deduct] paragraph 8 as follows: 更改14.8.2 [temp.deduct]第8段如下:

If a substitution results in an invalid type or expression, type deduction fails. 如果替换导致无效的类型或表达式,则类型推导失败。 An invalid type or expression is one that would be ill-formed if written using the substituted arguments. 如果使用替换参数写入,则无效的类型或表达式将是格式错误的。 [Note: Access checking is not done as part of the substitution process. [注意:访问检查不是替换过程的一部分。 —end note] Consequently, when deduction succeeds, an access error could still result when the function is instantiated. -end note]因此,当演绎成功时,实例化函数时仍可能导致访问错误。 Only invalid types... 只有无效的类型......

So my interpretation is that this is impossible in C++03, but C++11 made it possible. 所以我的解释是在C ++ 03中这是不可能的,但是C ++ 11使它成为可能。

I don't think so. 我不这么认为。

11/4 "Member access control" (C++03): 11/4“会员访问控制”(C ++ 03):

The interpretation of a given construct is established without regard to access control. 建立对给定构造的解释而不考虑访问控制。 If the interpretation established makes use of inaccessible member names or base classes, the construct is ill-formed. 如果建立的解释使用了不可访问的成员名称或基类,则该构造是不正确的。

So overload resolution occurs first, then access control is applied. 因此首先发生重载决策,然后应用访问控制。

Here is an example that implements is_comparable and handles a potentially private operator==. 这是一个实现is_comparable并处理潜在私有运算符==的示例。 g++-4.7 chokes on this, but g++-4.8 and clang++ 3.4 handle it correctly in C++11 mode. g ++ - 4.7 chokes,但g ++ - 4.8和clang ++ 3.4在C ++ 11模式下正确处理它。

#include <iostream>
#include <utility>
// is_comparable trait
template<class T>
class is_comparable {
  template<typename U> static char (&check (int))[1 + sizeof (decltype (
    std::declval<U>() == std::declval<U>() // trait check
  ))];
  template<typename>   static char (&check (...))[1];
public:
  static constexpr const bool value = sizeof (check<T> (0)) != 1;
};
// tests
class Diff1 {};          // non-comparable
class Diff2 {            // non-comprable, since member is private
  bool operator== (const Diff2&);
};
struct EqM { bool operator== (EqM); };  // comparable
struct EqG {};                          // comparable
bool operator== (const EqG&, const EqG&);
int
main ()
{
  std::cout << "is_comparable:";
  std::cout << " void=" << is_comparable<void>::value;
  std::cout << " Diff1=" << is_comparable<Diff1>::value;
  std::cout << " Diff2=" << is_comparable<Diff2>::value;
  std::cout << " int=" << is_comparable<int>::value;
  std::cout << " EqM=" << is_comparable<EqM>::value;
  std::cout << " EqG=" << is_comparable<EqG>::value;
  std::cout << "\n";
  return 0;
}
// $ clang++ is_comparable.cc -std=c++11 && ./a.out
// is_comparable: void=0 Diff1=0 Diff2=0 int=1 EqM=1 EqG=1

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM