4

I was trying to make a simple function that allowed checking if a string was in a given list. Here is some demo code:

#include <string>
#include <iostream>
#include <set>
#include <initializer_list>

template<typename T2, typename T>
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;
    }
  }
}

As you can see I am trying to check if a std::wstring is in a list of const wchar_t*consts.

This compiles with the MS compiler (and seems to work) but GCC complains that no types to make it work can be derived. Interestingly it also doesn't compile with the MS compiler anymore if I switch the order of the template parameters so the 6th line reads:

template<typename T, typename T2>

In that case the compiler says T is ambiguous.

I've tried a few variations like using only one template parameter but then I can't call it with strings and pointers anymore.

How do I do this - if possible - properly?

2 Answers 2

2

Your code compiles in GCC 4.8.1 with the addition of:

#include <algorithm>

std::find is declared in <algorithm>. The C++ Standard Library that ships with MSVC often brings in seemingly unnecessary headers. I'm betting is tagging along with <set> or <initializer_list>.

A working example can be found here.

Sign up to request clarification or add additional context in comments.

3 Comments

Now I wonder if it is a bug that the template parameter order matters to the MS compiler. Maybe I'll open another question.
Do you have any idea why it would find version of std::find without the include but not the correct one?
@Sarien, based on the error message, it is seeing a find that comes along with <iostream>, overloaded for streambufs. Library vendors have some leeway when it comes to which headers things are actually in, provided it is declared when you do include the proper headers. It's likely that moving this overload to <algorithm> would have meant including types associated with streams when the user included <algorithm> and they picked the better of the two options.
2

You're grabbing a wrong overload of find (best effort - the compiler can't find the intended one), you need to include

#include <algorithm>

This is also true for gcc 4.9.0

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.