2017-11-19 27 views
0

type의 별칭을 final으로 표시 할 수 있습니까? (파생 클래스에서 다시 정의 할 수 없음)?"typedef"를 최종화 (또는 시뮬레이션)

#include <iostream> 
class B{ 
    public: using type=std::string; 
}; 
class D : public B{ 
    public: using type=int;  //<--- [1] I want a compile error here. 
}; 
int main(){ 
    typename D::type str="abc"; //<--- [2] This line is actually correct. 
} 

http://en.cppreference.com/w/cpp/language/final에 따르면, 단지 함수이다.
해결 방법이 있습니까?

어떤 경우에는 바보 같은 코더로 유용합니다.

+0

처음에는 형식 별칭을 무시할 수 없으므로 '최종'은 오해의 소지가 있습니다. – chris

+0

@chris 감사합니다. 동의합니다.나는 또한 틀린 낱말을 ... 아마 사용한다 ... 아직도 정확한 것을 모른다. – cppBeginner

+0

당신이 말할 때 _/<--- [2]이 줄은 실제로 correct_, 당신이 원하는 것을 의미합니다. 권리? 'str' var은 당신이 그것을 다시 정의하기 때문에'int' 타입이어야합니다. – realharry

답변

4

아니요, 불가능합니다.

특성 기반 유형은 가능하지만 기계는 추악합니다.

어쩌면 adl 기반 태그 기능 맵을 통해 분산 형 맵을 정의 할 수 있습니다.

template<class T>struct tag_t{constexpr tag_t(){} using type=T;}; 
template<class T>constexpr tag_t<T> tag{}; 

namespace trait { 
    template<class T> 
    constexpr void type_tag(tag_t<T>){} 
    template<class T> 
    using type=typename decltype(type_tag(tag<T>))::type; 
} 

// non-final alias 
struct A{ 
    friend constexpr tag_t<int> type_tag(tag_t<A>){return {};} 
}; 
// non-final alias 
struct A{ 
    friend constexpr tag_t<char> type_tag(tag_t<A>){return {};} 
}; 
// final alias 
struct B{ 
    template<class T, std::enable_if_t< std::is_base_of<B,T>{}, bool> =true> 
    friend constexpr tag_t<std::string> type_tag(tag_t<T>){return {};} 
}; 

지금 trait::type<>Atype_tag 작품을 무시하지만 B와 같은를하려고하면 당신은 긴 이해할 수없는 오류가 발생합니다.

이것은 나쁜 계획입니다.

메타 클래스를 사용하면 이와 비슷한 작업을 수행 할 수 있습니다.

일반적으로이 두 가지 모두 C++의 새로운 하위 언어를 작성해야 C++에서 시행하지 않는 제약 조건을 적용해야합니다. 가능한 아주 좋은 이유가없는 한 가능하지 않지만 부주의합니다.

+0

tag-magic으로 많은 질문에 답한 것은 재미 있습니다. 나는 또한 당신이 큰 번호 로이 하나를 대답 감히 만족합니다. 감사. – cppBeginner

1

형식을 유용하게 숨기기 위해 열거 형이나 다른 인형을 사용할 수있는 방법에 대한 접선 응답입니다.

/* 
* Imagine everybody uses managed strings in our project throughout, 
* so everyone expects to be able to declare and print strings everywhere, 
* especially for debugging... 
*/ 
typedef OurInternalMangedStrings string; 
/***/ 

void InternalStringManager::ReallyDoingNastyInternalStuff() 
{ 
    // Within this code casually using managed strings 
    // to format error messages, etc, 
    // would be fatal as it will cause nasty recursion. 
    enum DoNotUseStrings_DeadlockDanger { string, OurInternalMangedStrings }; 
    printError(string ("I had an error here and I don't know why - code ") << errCode); 

} 

는 단서를주는 희망 문자열과 DoNotUseStrings_DeadlockDanger 모두 언급 할 것이다 오류가 발생합니다.

하지만 "문자열"이라는 단어를 작성자가 사용하지 못하도록 제한하고 있으므로 자동으로 변환을 수행하지 못하도록하거나 이미 존재하는 유형의 객체를 사용하지 않습니다. 개인적으로

void MyManager::Setup() 
{ 
    { SomeFeature newPimple = new Somefeature; 
     enum DoNotUseMember {someFeature}; 

     /** set up newPimple using other member data and parameters 
      when it is ready I will assign it to the member variable "someFeature" 
      **/ 
     /** any accidental use of a someFeature member will produce error message **/ 
     // Ready to install the new pimpl as the visible feature 
     MUTEX_RAII(access_feature); // ... Or whatever might be needed 
     /* can still access someFeature by being explicit */ 
     delete this->someFeature; 
     this->someFeature = newPimpl; 
    } 
    /** other setup code that uses the new feature **/ 
} 

, 나는 새로운 인스턴스 someFeature를 호출하고 숨어 동작을 얻을 것입니다 : 데이터 값에 대한

printError("I had an error here and I don't know why at all!"); 

내가 더 유용 찾을 : 생성자는 명시하지 않은 경우 의견없이 통과 할 것이다 다음 무료지만 많은 사람들이 n을 찾는다. 재사용하기 어렵다.

이 기술을 사용하는 또 다른 방법은 리팩토링입니다. 구성원의 값을 행복하게 사용하여 그 동작을 제어하는 ​​방법이 있습니다. 그런 다음 제어 값 중 하나를 외부에서 제어해야하는 부분이 개선되어야합니다. 이를 구현하기 위해 원래의 인수가없는 메소드는 심 (shim)이되어 멤버를 인수로 사용하여 새 메소드를 호출합니다.

그러나 새 방법이 실수로 인수 대신 멤버를 사용하지 않도록하는 방법은 무엇입니까? 개인적으로, 나는 논쟁의 가면을 회원으로 만들 것이지만 우리는 다른 사람들의 이해력에 의해 다시 제한을 받는다.

+0

감사합니다. 유용하고 창조적입니다. – cppBeginner