[C++] switch에서 문자열 사용하기 (feat. constexpr)

Bard·2022년 1월 3일
2

문제상황

사실 switch에서 문자열을 쓰는 방법은 굉장히 다양하다. map을 써서 enum 형태로 반환되는 함수를 쓸 수도 있을 것이고, 아예 switch 자체를 구현할 수도 있을 것이다.

하지만 오늘 공부한 내용은 좀 활용가치가 높은 것 같아서 기록해두려고 한다.

switch는 특성상 case 다음에 무조건 상수 표현식이 있어야 한다.

그렇기 때문에 일반적인 함수로는 다음과 같은 코드를 만들 수 없다.

unsigned int Hash(const char* s);

//main
switch(Hash(input)){
	case Hash("Insert"): {
	~~~
	}
}

constexpr 이란?

C++11에 constexpr 이라는 키워드가 추가되었다.

constexpr은 변수 또는 함수의 값을 컴파일 시점에 도출하여 상수화 시켜주는 아주 강력한 기능이다.

컴파일 시점에 상수로 처리되기 때문에 switch case 문에서도 상수로 취급된다!

이를 통해 다음과 같은 코드를 만들 수 있다.

constexpr unsigned int Hash(const char* s);

//main
switch(Hash(input)){
	case Hash("Insert"): {
	~~~
	}
}

constexpr을 함수에 사용할 때 제약사항

constexpr을 사용하는 데 있어서 몇가지 제약사항이 있는데 간단하게 정리하고 마무리한다.

  • 반환값이 무조건 Literal Type이어야 한다.
  • virtual로 재정의된 함수가 아니어야 한다.
  • 재귀 함수로 사용할 수 있다.
  • 함수에 constexpr을 붙일 경우 inline을 암시한다.
  • C++11에서는 함수 본문에 지역변수를 둘 수 없고, 하나의 return 구문만 있어야 했다.
  • 위 제약은 C++14에서 사라졌다.

구현 예시

다음은 백준의 17347번 Text Editor를 풀이한 코드이다.

#include <bits/stdc++.h>
#include <ext/rope>

using namespace std;
using namespace __gnu_cxx;
using ll = long long;

constexpr unsigned int Hash(const char* str){
  return str[0] ? static_cast<unsigned int>(str[0]) + 0xEDB8832Full * Hash(str + 1) : 8603;
}

char s[1048577];
crope rp;
int pos = 0;

void execute(const char* operation);

int main(){
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  
  int t;
  
  cin >> t;
  while(t--){
    char operation[10];
    cin >> operation;
    execute(operation);
  }
}

void execute(const char* operation){
  switch(Hash(operation)){
    case Hash("Move"): {
      int k;
      cin >> k;
      pos = k;
      break;
    }
    case Hash("Insert"): {
      int len, tmpPos = pos;
      cin >> len;
      while(len>0){
        cin.getline(s, 1048577);
        len -= strlen(s);
        rp.insert(pos, s);
        pos += strlen(s);
      }
      pos = tmpPos;
      break;
    }
    case Hash("Delete"): {
      int len;
      cin >> len;
      rp.erase(pos, len);
      break;
    }
    case Hash("Get"): {
      int len;
      cin >> len;
      cout << rp.substr(pos, len) << '\n';
      break;
    }
    case Hash("Prev"): {
      pos--;
      break;
    }
    case Hash("Next"): {
      pos++;
      break;
    }
  }
}

Reference

Microsoft Docs - constexpr(C++)
[C++] switch 문에서 문자열 사용하기 (Feat. constexpr)

profile
The Wandering Caretaker

0개의 댓글