2016-09-23 2 views
3

확인을위한 구조를 제공하려고 시도했습니다. A은 (캐스팅 선택) - 캐스팅 가능 B입니다. 네 개의 모든 캐스트는 정확히 동일한 구현을 가지며 이름이 필요합니다 (로컬 매크로 가능 정의가 가능할 수도 있지만 필요하지는 않음). 나는 많은 체크인을 위해 운영 구조, 예를 들어 쓴 :static/dynamic/const/reinterpret_cast를 평가되지 않은 컨텍스트에서 사용할 수 있습니까?

#include <iostream> 
#include <type_traits> 
#include <string> 

template<class, class, class, class = void> 
struct is_valid_ternary_operator : std::false_type 
{ }; 

template<class T, class S, class R> 
struct is_valid_ternary_operator <T, S, R, 
            std::void_t<decltype(std::declval<T>() ? 
                 std::declval<S>() : 
                 std::declval<R>())>> : std::true_type 
{ }; 

int main() 
{ 
              //true? 1 : 0 //is ok 
    std::cout << is_valid_ternary_operator<bool, int, int>::value << std::endl; 
              //true? 1 : std::string("0") //would be error 
    std::cout << is_valid_ternary_operator<bool, int, std::string>::value << std::endl; 
              //true? std::string("1") : std::string("0") //ok 
    std::cout << is_valid_ternary_operator<bool, std::string, std::string>::value << std::endl; 
              //std::string("1")? 1 : 0 //error 
    std::cout << is_valid_ternary_operator<std::string, int, int>::value << std::endl; 
} 

Live example

예상 출력이 표시됩니다.

main.cpp:12:84: error: template argument 1 is invalid 
    (std::declval<T>()))>> : std::true_type 
         ^~ 
main.cpp:12:94: error: template argument 3 is invalid 
    (std::declval<T>()))>> : std::true_type 
            ^~~~~~~~~ 

Live

이 평가되지 않은 상황에서 캐스트를 사용하지

을 허용 :

template<class T, class S, class = void> 
struct is_static_cast_able : std::false_type 
{ }; 

template<class T, class S> 
struct is_static_cast_able<T, S, 
          std::void_t<decltype(static_cast<std::declval<S>()> 
                  (std::declval<T>()))>> : std::true_type 
{ }; 

를하지만 오류가 발생 :하지만 지금 캐스트와 같은 일을 생각?

+6

'static_cast'는'<>'대괄호 안에 * 유형 *이 있어야합니다. 'std :: declval ()'은 * 표현식 *입니다. 당신은 단지'static_cast (std :: decl ())' – aschepler

답변

3

평가되지 않은 컨텍스트의 캐스트를 사용할 수 있습니까?

짧은 답변 : 예, 허용됩니다.


어쨌든, 나는 예제를 최소한으로 줄이려고 노력할 것입니다.
표현식 그들이의 피연산자 (sizeofnoexcept, decltype, typeid)을 명시 적으로하지 않는 한 반대를 언급 평가되지 않은 있습니다 사업자와 함께 작동 할 것으로 예상된다 캐스트 것을 참고. 예를 들어

, sizeof는 평가되지 않은 상황이다
int main() { 
    unsigned int i; 
    sizeof(static_cast<int>(i)); 
} 

훨씬 쉽게 예를 들어, 그것은 작동합니다.
decltype를 사용하여 표시 할 수 있습니다 같은, 피연산자가있는 평가되지 않은뿐만 아니라 있습니다

int main() { 
    unsigned int i; 
    decltype(static_cast<int>(i)) j = i; 
} 

등등, 우리는 noexcept와 모두 비슷한 수행 할 수 있습니다

int main() { 
    unsigned int i; 
    bool b = noexcept(static_cast<int>(i)); 
} 

그리고 typeid과를 :

#include <typeinfo> 

int main() { 
    unsigned int i; 
    auto b = typeid(static_cast<int>(i)).name(); 
} 
+1

을 원하고있는 것처럼 보입니다. 작동하지 않으므로 새로운 질문을 던지면 안됩니다. 내 계발에 감사드립니다. 깨달음에 감사드립니다. – xinaiz

+0

@BlackMoses 안녕하세요. – skypjack

2

는 C++ 표준 라이브러리. std::is_convertible.

귀하의 질문에 : static_cast은 항상 컴파일 시간을 의미하지는 않습니다. 예를 들어, 정수 및 부동 소수점 유형의 변환에서 컴파일 타임에 컴파일 할 수없는 경우 컴파일러는 변환을위한 코드를 방출하기로 선택할 수 있습니다. 그래도. 그것은 평가되지 않은 맥락에서 나타날 수 있습니다.매우 제한되어 ++ C에서

평가되지 않은 피연산자 : 컨텍스트는 다음과 같습니다

  • decltype
  • sizeof
  • typeid
  • noexcept

는, ++ 표준 초안을 C를 인용하자면 [expr/8]

일부 상황에서, 평가되지 않은 피연산자가 표시 ([expr.typeid], [expr.sizeof], [expr.unary.noexcept], [dcl.type.simple]). 평가되지 않은 피연산자는 평가되지 않습니다. 평가되지 않은 피연산자는 으로 전체 표현식으로 간주됩니다.


참고 :

template<class T, class S, class = void> 
struct is_static_cast_able : std::false_type 
{ }; 

template<class T, class S> 
struct is_static_cast_able<T, S, 
     std::enable_if_t< 
      std::is_convertible<T, S>::value || 
      std::is_base_of<std::decay_t<T>, std::decay_t<S>>::value || 
      std::is_base_of<std::decay_t<S>, std::decay_t<T>>::value || 
      std::is_base_of<std::remove_pointer_t<T>, std::remove_pointer_t<S>>::value || 
      std::is_base_of<std::remove_pointer_t<S>, std::remove_pointer_t<T>>::value || 
      (std::is_same<T, void*>::value && std::is_pointer<S>::value) || 
      (std::is_same<S, void*>::value && std::is_pointer<T>::value) 
     > 
    > 
: std::true_type { }; 
: std::is_convertible 따라서 static_cast

의 모든 경우에 적용되지 않습니다는 완전성을 위해서, 이것은 당신이 static_cast의 거의 모든 경우를 포함하는, is_static_cast_able 수행 할 작업입니다

다음 테스트 코드는 다음을 통과합니다.

struct A {}; 
struct B : public A {}; 

int main() 
{ 
    static_assert(is_static_cast_able<int, char>::value, ""); 
    static_assert(is_static_cast_able<double, int>::value, ""); 
    static_assert(is_static_cast_able<int, double>::value, ""); 
    static_assert(is_static_cast_able<void*, double*>::value, ""); 
    static_assert(is_static_cast_able<double*, void*>::value, ""); 
    static_assert(is_static_cast_able<B, A>::value, ""); 
    static_assert(is_static_cast_able<A, B>::value, ""); 
    static_assert(is_static_cast_able<B&, A&>::value, ""); 
    static_assert(is_static_cast_able<B*, A*>::value, ""); 
    static_assert(is_static_cast_able<A&, B&>::value, ""); 
    static_assert(is_static_cast_able<A*, B*>::value, ""); 
} 

Live on Coliru

관련 문제