web-dev-qa-db-ja.com

C ++ 17のあいまいなエラー(テンプレートテンプレートパラメーターとデフォルト引数の問題)

c++14およびc++17標準フラグを使用して、g ++によって異なる解釈がされるコードがあります。

#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 = 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)

C++ 17標準の観点からは、このコードの何が問題になっているのか理解できません。

26
Yuri Dolotkazin

C++ 17以降、動作が変更されました。

C++ 17より前は、 _std::vector_ に2つのテンプレートパラメーターがあるため、コードは機能します(2番目のパラメーターにはデフォルトの引数_std::allocator<T>_があります) )、テンプレートテンプレートパラメータVectorは1つしかないと宣言されていますが、一致しないため、2番目の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
_
31
songyuanyao