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

Статическая закрытая функция с шаблоном в качестве аргумента по умолчанию в С++

У меня есть следующий код С++ 17:

template <typename Callback = void(*)()>
struct A {
    A(Callback c = &noop) {}
private:
    static void noop() {}
};

int main() {
    A a{};
}

Clang 6 компилирует это без каких-либо ошибок, но GCC 8.2 говорит:

In function ‘A(Callback)-> A<Callback> [with Callback = void (*)()]:
3:24: error: ‘static void A<Callback>::noop() [with Callback = void (*)()] is private within this context
  A(Callback c = &noop) {}
                 ^~~~~
5:14: note: declared private here
  static void noop() {}
              ^~~~

Интересно, что если Callback - это не аргумент шаблона, а простой псевдоним типа (т.е. Если я пишу, using Callback = void (*)() внутри класса A), оба компилятора в порядке. Кроме того, если вместо A a{}; Я явно пишу A<> a{}; , оба компилятора снова прекрасны. Это заставляет меня думать, что эта проблема каким-то образом связана с новым механизмом вычитания шаблона класса С++ 17.

Мой вопрос: кто из компиляторов прав в соответствии со стандартом? Является ли это ошибкой GCC или Clang является слишком разрешительным?

4b9b3361

Ответ 1

CTAD, как правило, происходит путем синтеза набора функций и шаблонов функций ([over.match.class.deduct] p1). В данном случае набор включает в себя:

Если C определен для каждого конструктора C, шаблон функции со следующими свойствами:

  • Параметры шаблона являются параметрами шаблона C за которыми следуют параметры шаблона (включая аргументы шаблона по умолчанию) конструктора, если таковые имеются.
  • Типы параметров функции - это параметры конструктора.
  • Тип возврата - это спецификация шаблона класса, назначенная аргументами C и шаблона, соответствующими параметрам шаблона C

Примечательно, что это исключает аргументы функции по умолчанию. Это почти наверняка дефект.

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


С точки зрения дизайна, я ожидал бы, что поведение Клана будет правильным.