Оператор [] для карты, которая не компилируется с использованием ограниченного перечисления в качестве ключа, но работает функция at (). Почему двусмысленность?

#c #visual-studio-2017 #c 17 #stdmap #enum-class

#c #visual-studio-2017 #c 17 #stdmap #enum-class

Вопрос:

У меня есть код, который выглядит следующим образом:

 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 = [amp;](const std::stringamp; str, const std::regexamp; 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() amp;amp; "invalid input, must contain at least 1 character.");
        // Fails to compile
        assert(match(sequence.data(), ValidSets[TYPE]) amp;amp; "invalid sequence set for this type."); 
        // Works
        assert(match(sequence.data(), ValidSets.at(TYPE)) amp;amp; "invalid sequence set for this type.");
        sequence_ = sequence;
    }
};
  

Тогда я попытаюсь использовать ее как таковую:

 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;
}
  

Однако ValidSets[TYPE] ошибка компилятора при компиляции в Visual Studio 2017 C2678 . Тем не менее, когда я меняю ее на use ValidSets.at(TYPE) , она компилируется и выполняется просто отлично…

Почему одна не компилируется, а другая работает?

Комментарии:

1. Потому что map это const , и [] является неконстантным методом.

2. Ну, я действительно знал это, но я просто вставил код в godbolt, и компилятор сказал мне 🙂

3. @cigien спасибо за напоминание и за ясность!

4. Кстати, сейчас это не имеет отношения к этому вопросу, но в будущем убедитесь, что хотя бы один из ваших тегов c . Таким образом, вы получите гораздо больше информации по этому вопросу.

5. не путайте [] с простым доступом к элементу. Это то, что вы получаете с at . [] делает что-то другое: он вставляет значение в map, если оно отсутствует, а затем возвращает ссылку