constexpr에서 std :: string을 사용할 수 있습니까?


175

C ++ 11, Ubuntu 14.04, GCC 기본 툴체인 사용 .

이 코드는 실패합니다 :

constexpr std::string constString = "constString";

오류 : constexpr 변수 'constString'의 'const string {aka const std :: basic_string}'유형은 리터럴이 아닙니다 ... 왜냐하면 'std :: basic_string'은 사소한 소멸자를 갖지 않기 때문입니다.

그것은 사용할 수 있습니다 std::stringA의 constexpr? (분명히 아닙니다 ...) 그렇다면 어떻게? 에서 문자열을 사용하는 다른 방법이 constexpr있습니까?


2
std::string문자 그대로의 유형은 아니다
표트르 Skotnicki

7
@PiotrS - 질문은 ... 말한다
벡터

4
@Vector constexpr이 무엇인지 물어 보았거나 왜 constexpr이되고 싶 std::string습니까? SO에는 여러 컴파일 타임 문자열 구현이 있습니다. 오류 메시지를 이해하고 리터럴 유형 만 constexpr로 만들 수 있다는 것을 알면 리터럴이 아닌 유형 constexpr을 만들 수 있는지 묻는 요점은 무엇입니까? 또한 constexpr 인스턴스를 원할 수있는 몇 가지 이유가 있으므로 질문을 분명히 제시하십시오.
Piotr Skotnicki

2
예 : @PiotrS. 거기에 constexpr문자열 구현이 있습니다. std::string그들 중 하나가 아닙니다.
tenfour

3
@PiotrS -SO에 여러 컴파일 타임 문자열 구현이 있습니다. 감사합니다. 그것은 나를위한 옵션이 아니지만 내 질문에 대답합니다 : std :: string이 작동하지 않습니다. 내가 fourfour에 말한 것처럼 std :: string을 사용하는 방법이 있는지 궁금합니다. 내가 알지 못하는 많은 트릭이 있습니다.
벡터

답변:


167

아니요, 컴파일러는 이미 포괄적 인 설명을 제공했습니다.

그러나 당신은 이것을 할 수 있습니다 :

constexpr char constString[] = "constString";

런타임에 이것은 std::string 필요할 때 .


78
왜 안돼 constexpr auto constString = "constString";? 그 추악한 배열 구문을 사용할 필요가 없습니다 ;-)
stefan

80
이 질문의 맥락에서 더 명확합니다. 요점은 어떤 문자열 유형을 선택할 수 있는지에 관한 것입니다. 사용할 데이터 유형을 강조하려고 할 char[]때보 다 더 자세하고 명확 auto합니다.
tenfour

7
@tenfour 맞습니다. 좋은 지적입니다. 나는 때때로 auto;-) 사용에 약간 집중하고 있다고 생각합니다.
stefan

1
@FelixDombek 아니오, 그러나 c ++ 17을 사용하면constexpr auto s = "c"sv;string_view
wich

6
해당 컨텍스트에서 char 배열을 constexpr하는 것이 합리적입니까? 문자열을 구성하는 데 사용하면 어쨌든 복사됩니다. 리터럴을 문자열의 생성자에 전달하는 것과 그러한 constexpr 배열을 전달하는 것의 차이점은 무엇입니까?
KjMag

167

현재로 20 ++ C , 예.

현재 C ++ (17) , 당신은 사용할 수 있습니다 string_view:

constexpr std::string_view sv = "hello, world";

A string_viewstring객체 시퀀스에 대한 불변의 비 소유 참조 역할을하는 유사 객체입니다 char.


6
이 상수를 함수에 전달할 때마다 const std::string&새로운 std :: string을 작성해야합니다. 그것은 보통 상수를 만들 때 생각했던 것과 반대입니다. 따라서 나는 이것이 좋은 생각이 아니라고 말하는 경향이 있습니다. 최소한 조심해야합니다.
Rambo Ramon

29
@RamboRamon은로 string_view암시 적으로 변환 할 수 string없으므로 실수로 stringfrom을 구성 할 위험이 거의 없습니다 string_view. 반대로, char const* 에 암시 적으로 변환 string하므로 사용이, string_view이런 의미에서 실제로 안전하다.
Joseph Thomson

4
설명해 주셔서 감사합니다. 나는 완전히 string_view암묵적으로 변환 할 수없는 것을 완전히 동의하고 잊어 버렸습니다 string. IMO에서 제기 한 문제는 여전히 유효하지만 string_view구체적으로 적용되지는 않습니다 . 사실, 당신이 언급했듯이, 그 점에서 더 안전합니다.
Rambo Ramon

5
이 답변이 string_view링크가 아니라 무엇인지 에 대해 더 많이 말하면 좋을 것 입니다.
eric

23

C ++ 20은 constexpr문자열과 벡터를 추가합니다

다음 제안 명백히 받아 들여 졌습니다 : http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0980r0.pdf 다음 과 같은 생성자를 추가합니다 :

// 20.3.2.2, construct/copy/destroy
constexpr
basic_string() noexcept(noexcept(Allocator())) : basic_string(Allocator()) { }
constexpr
explicit basic_string(const Allocator& a) noexcept;
constexpr
basic_string(const basic_string& str);
constexpr
basic_string(basic_string&& str) noexcept;

모든 / 대부분의 메소드의 constexpr 버전 외에도.

GCC 9.1.0부터는 지원되지 않으며 다음은 컴파일되지 않습니다.

#include <string>

int main() {
    constexpr std::string s("abc");
}

와:

g++-9 -std=c++2a main.cpp

오류가있는 경우 :

error: the type const string {aka const std::__cxx11::basic_string<char>’} of constexpr variable s is not literal

std::vector논의 : constexpr std :: vector를 만들 수 없습니다

우분투에서 테스트 19.04.


19

문제는 사소하지 않은 소멸자이므로 소멸자가에서 제거되면 해당 유형 std::stringconstexpr인스턴스 를 정의 할 수 있습니다 . 이렇게

struct constexpr_str {
    char const* str;
    std::size_t size;

    // can only construct from a char[] literal
    template <std::size_t N>
    constexpr constexpr_str(char const (&s)[N])
        : str(s)
        , size(N - 1) // not count the trailing nul
    {}
};

int main()
{
    constexpr constexpr_str s("constString");

    // its .size is a constexpr
    std::array<int, s.size> a;
    return 0;
}

18
이것은 C ++ (17)가 무엇을 기본적으로 string_view그 제외입니다 string_view대부분의 기능을 제공에서 당신이 알고std::string
느릅 나무
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.