g ++ 8.1模板推导歧义,std标志等于'c ++ 17'

Yur*_*zin 26 c++ templates language-lawyer c++14 c++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;
}
Run Code Online (Sandbox Code Playgroud)

当我尝试使用命令编译此代码时

g ++ -std = c ++ 14 -Wall -pedantic main.cpp

一切正常.

但是,当我尝试使用命令编译此代码时

g ++ -std = c ++ 17 -Wall -pedantic 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)
Run Code Online (Sandbox Code Playgroud)

从C++ 17标准的角度来看,我无法弄清楚这段代码有什么问题.

son*_*yao 31

自C++ 17以来,行为发生了变化.

在C++ 17之前,代码有效,因为std::vector有两个模板参数(第二个具有默认参数std::allocator<T>),而模板模板参数Vector声明只有一个,它们不匹配,那么第二个func将不被考虑.

从C++ 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
Run Code Online (Sandbox Code Playgroud)