1

I'm getting the standard

error C2678: binary '==' : no operator found which takes a left-hand operand of type 'std::string' (or there is no acceptable conversion)

error. However, I have included string, and there is no apparent way for me to explain this.

Here is my code.

#include <string>
#include <vector>
#include <type_traits>

// [...]
template <typename T>
class Graph {
private:
    // [...]
    struct Vertex {
        T name;
        // [...]
    };
    std::vector<Vertex> verts;
public:
    // [...]
    template <typename P>
    int vertex(P item) {
        if (std::is_same<P,T>::value) {
            for (unsigned int i = 0; i < verts.size(); i++){
                if (verts[i].name == item) {
                    return i;
                }
            }
        } else if (std::is_same<P,int>::value) {
            return item;
        }
        return -1;
    }
}

The compiler is VS2012, the platform is Windows 8.1 64bit.

5
  • 1
    If P is not a string, your code will fail. C++ is not a dynamic language - your code is evaluated at compile time. You make provisions for the case when P is an int - indicating you expect that possibility. But in that case, your code will fail to compile, because you're still comparing it with a string. Commented May 18, 2014 at 0:14
  • I was under the impression from This SO Question that C++ can switch branches at compile time based on inference. Commented May 18, 2014 at 0:20
  • @PythonNut, if makes a decision at runtime. It's not conditional compilation. The condition, in this case, is a compile-time value, but it's still used during runtime. Commented May 18, 2014 at 0:33
  • So is the code in the linked question invalid? Basically P, my method is completely wrong? I was hoping std could pull off some magic with macros or something... oh well. Commented May 18, 2014 at 0:35
  • 2
    No, C++ will not switch branches with runtime if. You need to use meta-programming facilities like std::enable_if to do what you're trying to accomplish Commented May 18, 2014 at 1:11

2 Answers 2

2

Making an educated guess, in if (verts[i].name == item) it seems that verts[i].name has been instantiated as a std::string while item hasn't been instantiated as a std::string. Thus, the compiler rightfully complains that there's no overloaded operator to compare a std::string against X.

Update:

Another guess is that X is being instantiated as an int or a double because if it was instantiated as a std::string the compiler would complain about attempting to convert a std::string to an int by returning it in Graph::vertex() member function.

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

3 Comments

verts[i] is of type Vertex, but verts[i].name is likely of type std::string
Very sorry, edited Question to specify the structure of Vertex.
I'm not sure this argument still applies... as both the LHS and RHS are of type std::string.
1

Seems like you just need two vertex methods, like this (no template):

int vertex(const T& item) {
  for (unsigned int i = 0; i < verts.size(); i++){
    if (verts[i].name == item) {
      return i;
    }
  }
}

int vertex(int item) {
  return item;
}

That won't work if T turns out to be int, but that doesn't seem likely to work with your original code either.

The above also fails to implement the default vector(SomeOtherType) case as returning a default -1. It will just fail to compile, which to me seems reasonable. YMMV.

1 Comment

I turns out this and some template parameter inference does exactly what I had in mind originally. Thanks.

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.