0

I have code that looks like this:

enum class MyTypes {
   TYPE_1 = 1,
   TYPE_2 = 2,
   TYPE_3 = 3
};

static const std::regex reg1("some unique expression");
static const std::regex reg2("some unique expression");
static const std::regex reg3("some unique expression");

static const std::map<MyTypes, std::regex> ValidSets = {
    {MyTypes::TYPE_1, reg1},
    {MyTypes::TYPE_2, reg2},
    {MyTypes::TYPE_3, reg3}
};

static const auto match = [&](const std::string& str, const std::regex& reg) -> bool {
    std::smatch base_match;
    return std::regex_match(str, base_match, reg);
};

template<MyTypes TYPE = MyTypes::TYPE_2> // defaulting to a specific type
class Foo {
    std::string sequence_{""};
public:
    const std::uint16_t Type = static_cast<uint16_t>(TYPE);         

    Foo() = default;
    Foo(const std::string_view sequence) {
        assert(!sequence.empty() && "invalid input, must contain at least 1 character.");
        // Fails to compile
        assert(match(sequence.data(), ValidSets[TYPE]) && "invalid sequence set for this type."); 
        // Works
        assert(match(sequence.data(), ValidSets.at(TYPE)) && "invalid sequence set for this type.");
        sequence_ = sequence;
    }
};

Then I'll be trying to use it as such:

int main() {
    Foo bar_d("some character sequence"); // must match the regex for the default type

    Foo<Type::TYPE1> bar_1("some character sequence"); // must match the regex for type 1
    Foo<Type::TYPE3> bar_3("some character sequence"); // must match the regex for type 3
 
    return 0;
}

However, ValidSets[TYPE] is failing to compile within Visual Studio 2017 compiler error C2678. Yet when I change it to use ValidSets.at(TYPE) it compiles and executes just fine...

Why does one fail to compile and the other work?

Francis Cugler
  • 7,788
  • 2
  • 28
  • 59
  • 3
    Because the `map` is `const`, and `[]` is a non-const method. – cigien Aug 19 '20 at 21:38
  • @cigien I should know that... I just don't use `map` all that often that I tend to forget... – Francis Cugler Aug 19 '20 at 21:39
  • 1
    Well, I did know that, but I just pasted the code into godbolt, and the compiler [told](https://godbolt.org/z/fbbKaM) me :) – cigien Aug 19 '20 at 21:40
  • @cigien Yeah I keep forgetting that when I have a const map, to use `at()` and not `[]`... When I do use maps that aren't const, this issue never comes up and `visual studio`'s compiler errors are sometimes unforgiving - a bit cryptic and hard to follow! – Francis Cugler Aug 19 '20 at 21:40
  • 1
    @cigien thank you for the reminder and for the clarity! – Francis Cugler Aug 19 '20 at 21:42
  • 2
    BTW, it's irrelevant for this question now, but in the future make sure at least one of your tags is c++. You'll get a lot more eyes on the question that way. – cigien Aug 19 '20 at 21:45
  • @cigien any suggestion on which tag I should drop? Visual Studio? enum-class? – Francis Cugler Aug 19 '20 at 21:47
  • For this post, sure, since it's unlikely to be a compiler specific error (but might be). But definitely you should drop `compiler-errors`. It's pretty useless IMO. – cigien Aug 19 '20 at 21:48
  • 1
    dont confuse `[]` to be simple element access. This is what you get with `at`. `[]` does something different: It inserts a value in the map if not present and then returns a reference – 463035818_is_not_an_ai Aug 19 '20 at 21:54
  • @idclev463035818 Yeah, sometimes it's the simple things you forget... however, that's why my map in this situation is `const` I don't want it to be modified! And it's `static` so there is only ever `1` `map`! – Francis Cugler Aug 19 '20 at 22:02

0 Answers0