Может ли SFINAE обнаруживать нарушения частного доступа? - PullRequest
15 голосов
/ 24 января 2012

Интересно, ответит ли я sfinae, если я проверю кого-то из учеников в классе, и он будет закрыт? Будет ли это ошибка, или она скажет нормально, или это будет ошибка sfinae?

Ответы [ 4 ]

11 голосов
/ 24 января 2012

Да.

РЕДАКТИРОВАТЬ: C ++ 11 Стандартная цитата из §14.8.2 [temp.deduct]

8 / Если подстановка приводит к неверному типу или выражению, вывод типа завершается неудачно. Недопустимый тип или выражение - это то, что было бы неправильно сформировано, если было бы написано с использованием замещенных аргументов. [Примечание: проверка доступа выполняется как часть процесса замены. —Конечная записка]

Это подсказывает мне, что private может вызвать ошибку SFINAE. Чтение на:

Только недопустимые типы и выражения в непосредственном контексте типа функции и ее типов параметров шаблона могут привести к ошибке вывода. [Примечание: оценка замещенных типов и выражений может привести к побочным эффектам, таким как создание специализаций шаблонов классов и / или специализаций шаблонов функций, генерация неявно определенных функций и т. д. Такие побочные эффекты не находятся в «непосредственном контексте» и могут привести к в программе плохо сформирован. - примечание конца]

«Непосредственный контекст» мне не так понятен ... но он не противоречит моей точке зрения:)

конец EDIT

Так что мне кажется, что он выдаст ошибку 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
  };

Существуют особые случаи в отношении контроля доступа в случае SFINAE.

5 голосов
/ 24 января 2012

Нет.Я нахожусь в дороге, и у меня нет стандарта, чтобы цитировать меня, но sfinae занимает места на этапе компиляции, где компилятор проверяет, существует ли имя вообще, и на более позднем этапе имеет место контроль доступа.

Это похоже на разрешение перегрузки, когда учитываются все имена, и частное совпадение лучше, но не компилируется, хотя есть другое совпадение, которое будет "хорошо", но не приватным.

Добавление:

Основная проблема 1170 гласит:

1170 Проверка доступа во время вывода аргумента шаблона
Раздел: 14.8.2 [temp.deduct]
Статус: FDIS. Отправитель: Adamczyk. Дата: 2010-08-03

[Голосование в РГ на совещании в марте 2011 года.]

Согласно 14.8.2 [temp.deduct] параграф 8,

Проверка доступа не является частью процесса замены.Следовательно, когда дедукция завершается успешно, ошибка доступа все еще может возникнуть, когда создается экземпляр функции.

Это имитирует способ проверки доступа в разрешении перегрузки.Однако опыт показывает, что это исключение ошибок доступа из-за сбоя вывода существенно усложняет Стандартную библиотеку, поэтому это правило следует изменить.

Предлагаемое решение (январь 2011 г.):

Изменение 14.8.2 [temp.deduct] параграф 8 следующим образом:

Если подстановка приводит к недопустимому типу или выражению, вывод типа не выполняется.Недопустимый тип или выражение - это то, что было бы неправильно сформировано, если было бы написано с использованием замещенных аргументов.[Примечание: проверка доступа не выполняется как часть процесса замены.- примечание конца] Следовательно, когда вычет успешен, ошибка доступа все еще могла бы произойти, когда функция создается.Только недопустимые типы ...

Итак, моя интерпретация состоит в том, что это невозможно в C ++ 03, но C ++ 11 сделал это возможным.

2 голосов
/ 24 января 2012

Я так не думаю.

11/4 «Контроль доступа членов» (C ++ 03):

Интерпретация данной конструкции устанавливается без учета контроля доступа.Если в установленной интерпретации используются недоступные имена членов или базовые классы, конструкция имеет неправильную структуру.

Таким образом, сначала выполняется разрешение перегрузки, затем применяется управление доступом.

1 голос
/ 24 июля 2014

Вот пример, который реализует is_comparable и обрабатывает потенциально приватный оператор ==.g ++ - 4.7 подавляет это, но 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...