Я потратил бесчисленные часы, чтобы выявить проблему с gcc. Я хотел протестировать нашу базу кода с другим компилятором, чтобы искать дополнительные предупреждения, которые Clang, возможно, пропустили. Я был шокирован тем, что практически половина проекта прекратила компиляцию из-за отказа в выводе аргумента шаблона. Здесь я попытался заглушить свой случай до самой простой части кода.
#include <type_traits>
struct Foo
{ };
// This is a template function declaration, where second template argument declared without a default
template <typename T, typename>
void foo(const Foo & foo, T t);
// This is a template function definition; second template argument now has a default declared
template <typename T, typename = typename std::enable_if<1>::type>
void foo(const Foo & foo, T t)
{
}
int main(int argc, char ** argv)
{
foo(Foo{}, 1);
return 0;
}
Игнорировать a 1
в std::enable_if<1>
. Очевидно, это постоянное значение, чтобы не усложнять ситуацию, когда это не имеет значения.
Этот фрагмент кода компилирует [1] с clang (с 3.4 по 4.0), icc (16, 17), Visual С++ (19.00.23506). В принципе, я не смог найти какой-либо другой компилятор С++ 11, который, кроме gcc (4.8 - 7.1), не компилирует этот фрагмент кода.
Вопрос в том, кто прав и кто здесь? Поддерживает ли gcc поведение в соответствии со стандартом?
Очевидно, что это не критическая проблема. Я могу легко переместить std::enable_if
в объявление. Единственной жертвой была бы эстетика. Но хорошо иметь возможность скрыть уродливые 100 символов длиной std::enable_if
фрагмента кода, который не имеет непосредственного значения для пользователя библиотечной функции, в реализации.
Пример Live на godbolt.org.