Подтвердить что ты не робот

g++ 8.1 Неопределенность вывода шаблона с флагом std, равным 'С++ 17'

У меня есть код, который по-разному интерпретируется g++ стандартными флагами c++14 и c++17:

#include <iostream>
#include <vector>

template<class T, class A>
void func(const std::vector<T, A>&v)
{
    std::cout << 1 << std::endl;
}

template<typename T, template <typename>class Vector>
void func(const Vector<T>&v)
{
    std::cout << 2 << std::endl;
}

void f()
{
    std::vector<int> v;
    func(v);
}

int main()
{
    f();
    return 0;
}

Когда я пытаюсь скомпилировать этот код с помощью команды

g++ -std = С++ 14 -Wall -патентный main.cpp

все работает отлично.

Но когда я пытаюсь скомпилировать этот код с помощью команды

g++ -std = С++ 17 -Wall -патентный main.cpp

Я получаю эту ошибку:

main.cpp: In function 'void f()':
main.cpp:19:11: error: call of overloaded 'func(std::vector<int>&)' is ambiguous
     func(v);
           ^
main.cpp:5:6: note: candidate: 'void func(const std::vector<_Tp, _Alloc>&) [with T = int; A = std::allocator<int>]'
 void func(const std::vector<T, A>&v)
      ^~~~
main.cpp:11:6: note: candidate: 'void func(const Vector<T>&) [with T = int; Vector = std::vector]'
 void func(const Vector<T>&v)

Я не могу понять, что не так с этим кодом из стандартной точки зрения С++ 17.

4b9b3361

Ответ 1

Поведение изменилось с С++ 17.

До С++ 17 код работает, потому что std::vector имеет два параметра шаблона (второй имеет аргумент по умолчанию std::allocator<T>), в то время как параметр шаблона шаблона Vector объявлен как один, они не 't, то вторая func не будет рассмотрена.

Поскольку С++ 17 (CWG 150), аргументы шаблона по умолчанию разрешены для аргумента шаблона шаблона в соответствии с параметром шаблона шаблона с меньшим количеством параметров шаблона. Это означает, что оба func становятся действительными кандидатами, а затем приводят к двусмысленности.

template<class T> class A { /* ... */ };
template<class T, class U = T> class B { /* ... */ };

template<template<class> class P> class X { /* ... */ };

X<A> xa; // OK
X<B> xb; // OK in C++17 after CWG 150
         // Error earlier: not an exact match