Компилируя проект с более старой версией g ++ (4.8.0, MinGW), я обнаружил, что этот код не компилируется:
template<typename T>
void foo() = delete;
template<>
void foo<int>(){}
int main() {
foo<int>();
return 0;
}
Кажется, что g ++ даже не пытается искать явные специализации, если видит, что базовый вариант удален
mitalia@mitalia:~/scratch$ /opt/mingw32-dw2/bin/i686-w64-mingw32-g++ -std=c++11 buggy_deleted_template.cpp
buggy_deleted_template.cpp: In function 'int main()':
buggy_deleted_template.cpp:8:14: error: use of deleted function 'void foo() [with T = int]'
foo<int>();
^
buggy_deleted_template.cpp:5:6: error: declared here
void foo<int>(){}
^
mitalia@mitalia:~/scratch$ /opt/mingw32-dw2/bin/i686-w64-mingw32-g++ --version
i686-w64-mingw32-g++ (rubenvb-4.8.0) 4.8.0
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Вместо этого g ++ 4.8.4 и 5.2 (в Linux) не жалуются. Это ошибка в более старой версии компилятора или серая область в стандарте?
добавление
Clang 3.4.1 тоже не нравится:
mitalia@mitalia:~/scratch$ clang++ -std=c++11 buggy_deleted_template.cpp
buggy_deleted_template.cpp:5:6: error: redefinition of 'foo'
void foo<int>(){}
^
buggy_deleted_template.cpp:5:6: note: previous definition is here
buggy_deleted_template.cpp:8:5: error: no matching function for call to 'foo'
foo<int>();
^~~~~~~~
buggy_deleted_template.cpp:2:6: note: candidate template ignored: substitution failure [with T = int]
void foo() = delete;
^
2 errors generated.
mitalia@mitalia:~/scratch$ clang++ --version
Ubuntu clang version 3.4-1ubuntu3 (tags/RELEASE_34/final) (based on LLVM 3.4)
Target: x86_64-pc-linux-gnu
Thread model: posix
(а также @Baum mit Augen в комментариях сообщает, что он все еще не работает в 3.7)
Я не знаю, будет ли следующее полезным, но я нашел отчет о дефекте 941: явная специализация удаленного шаблона функции со статусом C ++ 11 в котором говорится следующее (Акцент мой):
В соответствии с пунктом 14.7.3 [temp.expl.spec], только не удаленные
шаблоны функций могут быть явно специализированными. Там нет
как представляется, насущная необходимость в этом ограничении, и это
может быть полезно запретить использование неявно-созданных экземпляров
специализации, в то же время позволяя использовать явно специализированные
версии.Предлагаемое решение (февраль 2010 года):
Изменить пункт 14.7.3 [temp.expl.spec] следующим образом:
Явная специализация любого из следующего:
не удаленныйшаблон функциишаблон класса
не удаленныйфункция-член шаблона классастатический член данных шаблона класса
член класса шаблона класса
шаблон класса члена класса или шаблон класса
не удаленныйшаблон функции-члена класса или класса
шаблонможно объявить …
Сейчас текущее состояние проекта стандарта N4527 является 14.7.3 Явная специализация [temp.expl.spec]:
1 Явная специализация любого из следующего:
(1.1) — шаблон функции
(1.2) — шаблон класса
(1.3) — переменный шаблон
(1.4) — функция-член шаблона класса
(1.5) — статический член данных шаблона класса
(1.6) — член класса шаблона класса
(1.7) — перечисление членов шаблона класса
(1.8) — шаблон класса члена класса или шаблон класса
(1.9) — шаблон функции-члена класса или шаблон класса
…
Так что я думаю:
template<typename T>
void foo() = delete;
template<>
void foo<int>(){}
int main() {
foo<int>();
return 0;
}
Является ли C ++ 11 стандартным совместимым кодом и должен быть принят.
Других решений пока нет …