2017-10-16 18 views
4

다음 예제에서 문자열 리터럴이 'v'으로 시작하지만 verify으로 시작할 수없는 경우 mainstatic_assert입니다.constexpr 함수 내부에서 문자열 리터럴에 조건을 정적으로 선언하는 방법은 무엇입니까?

왜 그런가? 문자열 리터럴의 문자 조건을 verify에서 static_assert까지 허용 할 수 있습니까?

#include <cstddef> 

template <std::size_t N> 
constexpr char get_first(const char (&str)[N]) 
{ 
    static_assert(N>1, "must be > 1"); 
    return str[0]; 
} 

template <std::size_t N> 
constexpr void verify(const char (&str)[N]) 
{ 
    static_assert(str[0] == 'v', "must start from v"); 
} 

int main() 
{ 
    static_assert(get_first("value") == 'v', "first must be 'v'"); // succeeds 
    verify("value"); // fails to compile 
} 

컴파일 오류 :

main.cpp: In instantiation of 'constexpr void verify(const char (&)[N]) [with long unsigned int N = 6]': 
main.cpp:19:15: required from here 
main.cpp:13:9: error: non-constant condition for static assertion 
     static_assert(str[0] == 'v', "must start from v"); 
     ^~~~~~~~~~~~~ 
main.cpp:13:9: error: 'str' is not a constant expression 

Example.

+0

당신은 내가 하나 제안, 문자열이 컴파일시 수 매개 변수가 주장 할 수있는 경우

verify([=] { return "value"; }); 

와 랩을 해제하는

처럼 통화가 보인다. – chris

답변

1

문제는 verify()

template <std::size_t N> 
constexpr void verify(const char (&str)[N]) 
{ 
    static_assert(str[0] == 'v', "must start from v"); 
} 

은 컴파일 시간 런타임 호출 할 수 있다는 것입니다.

static_assert() (str)을 컴파일 타임에 호출 할 수 있기 때문에 오류가 발생하지만 런타임 (str의 첫 번째 문자가 컴파일 타임에 알려지지 않은 경우)에서는 호출 할 수 없으므로 오류가 발생합니다.

- 편집 -

영업 리터럴 문자열을 통해 컴파일 시간 체크를 부탁드립니다.

다음은 바보 같은 예를 들어 내가 정말 유용하지 가정,하지만 난 당신을 위해 또 다른 해결 방법이 영감

template <char const * const str> 
constexpr bool startWithUpperLetter() 
{ 
    static_assert(str[0] != 'v', "no start with \'v\', please"); 

    return (str[0] >= 'A') && (str[0] <= 'Z'); 
} 

constexpr char const str1[] { "ABC" }; 
constexpr char const str2[] { "abc" }; 
constexpr char const str3[] { "vwx" }; 

int main() 
{ 
    static_assert(startWithUpperLetter<str1>() == true, "!"); 
    static_assert(startWithUpperLetter<str2>() == false, "!"); 
    // static_assert(startWithUpperLetter<str3>() == false, "!"); // error 
} 
+0

함수 또는 함수 호출이 생각보다 실행 시간이 길어 지거나 생각보다 적은 컴파일 시간을 갖는 언어 규칙이 있습니까? –

+0

@NickyC - 질문을 이해할 수는 없지만 'constexpr'이 없으면 함수는 (이상적으로) 런타임에만 있습니다. 'constexpr'은 실행 시간 **이고 ** 컴파일 시간은 활성화되어 있고 나는 컴파일 타임이 가능하도록하는 방법을 몰라요; 만약 당신이 컴파일 시간에만 작동하는 것을 원한다면, 나는 당신이 템플릿 메타 프로그래밍 작업을해야한다고 생각한다. – max66

+0

@ max66'static_assert' 할 수 있도록'verify '의 평가가 컴파일시에만 발생하도록 강제하는 방법이 있습니까? 템플릿 메타 프로그래밍을 사용하여 문자열 리터럴의 문자를 분석 할 수있는 방법이 있습니까? –

2

이 될 수 있기를 바랍니다. 이것은 static_assert을 사용하지 않지만 컴파일 타임에 조건을 적용하도록 보장됩니다.

#include <type_traits> 
template<bool b> 
using enforce = std::bool_constant<b>; 

template <std::size_t N> 
constexpr int verify(const char (&str)[N]) 
{ 
    if(get_first(str) != 'v') { 
     throw "must start from v"; 
    } 
    return 0; 
} 

int main() 
{ 
    using assertion = enforce<verify("value")>; // compiles 
    using assertion = enforce<verify("fail")>; // fails to compile 
    // or use it like 
    constexpr auto assertion0 = verify("value"); // compiles 
} 

이렇게 throwing은 constexpr 컨텍스트에서 유효하지 않습니다. 당신이 받게됩니다 오류는 다음과 같이 somethign 모양 :

26 : <source>:26:31: error: non-type template argument is not a constant expression 
    using assertion = enforce<verify("fail")>; // fails to compile 
           ^~~~~~~~~~~~~~ 
15 : <source>:15:9: note: subexpression not valid in a constant expression 
     throw "must start from v"; 
     ^
26 : <source>:26:31: note: in call to 'verify("fail")' 
    using assertion = enforce<verify("fail")>; // fails to compile 

우리는 템플릿 인수로 사용하여 verify의 constexpr 평가를 적용 할 수 있습니다. 비 void 반환 형식을 선언하는 이유이기도합니다.

+2

또 다른 방법은'verify()'의 값을'constexpr' 값에 저장하는 것입니다; 예제 :'constexpr int vr0 = verify ("value"); constexpr int vr1 = verify ("실패");'; 이 경우에는'시행 '할 필요가 없다. – max66

3

C++ 17에서는 constexpr 람다 (online demo)의 값을 래핑 할 수 있습니다. 당신이

template <class StringWrapper> 
constexpr void verify(StringWrapper str_w) 
{ 
    constexpr auto str = str_w(); 
    static_assert(str[0] == 'v', "must start from v"); 
}