Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the order of template parameters matter to the MS C++ compiler in this example?

The following code compiles fine in GCC but in Visual Studio it results in

error C2782: 'bool contains(const T &,const std::initializer_list<T2> &)' : template parameter 'T' is ambiguous see declaration of 'contains' could be 'const wchar_t *' or 'std::wstring'

It does however compile and work if the order of the template parameters is given as

template<typename T2, typename T>

Is this a compiler bug?

#include <string> #include <iostream> #include <set> #include <initializer_list> #include <algorithm>  template<typename T, typename T2> bool contains(T const& value, std::initializer_list<T2> const& set) {   return std::find(std::begin(set), std::end(set), value) != std::end(set); }  int main(void) {   std::set<std::wstring> values = { L"bar", L"not" };    for (std::wstring val : values) {     std::wcout << "\"" << val << "\" ";     if (contains(val, { L"foo", L"bar", L"baz", L"doom" })) {       std::wcout << "found" << std::endl;     }     else {       std::wcout << "not found" << std::endl;     }   } } 

Edit: I have created a bugreport: https://connect.microsoft.com/VisualStudio/feedbackdetail/view/982338/template-parameter-order-matters

like image 463
Sarien Avatar asked Sep 26 '14 13:09

Sarien


People also ask

Which is the correct example of template parameters?

For example, given a specialization Stack<int>, “int” is a template argument. Instantiation: This is when the compiler generates a regular class, method, or function by substituting each of the template's parameters with a concrete type.

Why do we use template template parameter?

Why we use :: template-template parameter? Explanation: It is used to adapt a policy into binary ones.

What is a non type template parameter?

A template non-type parameter is a template parameter where the type of the parameter is predefined and is substituted for a constexpr value passed in as an argument. A non-type parameter can be any of the following types: An integral type. An enumeration type. A pointer or reference to a class object.


2 Answers

I remember that VS has a bug where they would do double-deduction in certain scenarios, and I think that's what's happening here. Clang also compiles it both ways, so since clang + gcc agree, it's likely a VS bug.

like image 72
Jared Grubb Avatar answered Sep 28 '22 04:09

Jared Grubb


I had a similar problem which was resolved by switching to the latest VS Pro version. I think this bug was addressed in the latest VS pro version as I remember seeing it in a change-log at some point.

like image 37
Adam893 Avatar answered Sep 28 '22 02:09

Adam893