g ++ 8.1 ambiguïté de la déduction du modèle avec l'indicateur std égal à 'c++17'

J'ai du code qui est interprété différemment par G++ avec les drapeaux standard c++14 et 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;
}

Quand j'essaie de compiler ce code avec la commande

G++ - std = C++14-MUR-pédant principal.rpc

Tout fonctionne très bien.

Mais quand j'essaie de compiler ce code avec la commande

G++ - std = C++17-MUR-pédant principal.rpc

Je reçois cette erreur:

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)

Je n'arrive pas à comprendre ce qui ne va pas avec ce code du point de vue de la norme C++17.

25
demandé sur Peter Mortensen 2018-08-17 13:13:50

1 réponses

Le comportement a changé depuis C++17.

Avant C++17, le code fonctionne car std::vector a deux paramètres de modèle (le 2ème a l'argument par défaut std::allocator<T>), alors que le paramètre de modèle de modèle Vector est déclaré pour avoir un seul, ils ne correspondent pas alors le 2ème func ne sera pas considéré.

Depuis C++17 ( CWG 150 ), les arguments de modèle par défaut sont autorisés pour qu'un argument de modèle de modèle corresponde à un paramètre de modèle de modèle avec moins de modèle paramètre. Cela signifie que les deux func deviennent des candidats valides et conduit ensuite à l'ambiguïté.

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
30
répondu songyuanyao 2018-08-17 10:38:05