developer tip

C ++에서 "using"키워드의 논리는 무엇입니까?

optionbox 2020. 8. 10. 07:57
반응형

C ++에서 "using"키워드의 논리는 무엇입니까?


C ++에서 "using"키워드의 논리는 무엇입니까?

그것은 다른 상황에서 사용되며 모든 사람들이 공통점을 가지고 있는지 찾으려고 노력하고 있으며 "using"키워드가 그렇게 사용되는 이유가 있습니다.

using namespace std; // to import namespace in the current namespace
using T = int; // type alias
using SuperClass::X; // using super class methods in derived class

C ++ 11에서 usingfor 사용시 키워드 type aliastypedef.

7.1.3.2

typedef-name은 별칭 선언으로도 도입 할 수 있습니다. using 키워드 다음의 식별자는 typedef-name이되고 식별자 다음의 선택적 attribute-specifier-seq는 해당 typedef-name에 속합니다. typedef 지정자에 의해 도입 된 것과 동일한 의미를 갖습니다. 특히 새로운 유형을 정의하지 않으며 type-id에 나타나지 않습니다.

Bjarne Stroustrup은 실용적인 예를 제공합니다.

typedef void (*PFD)(double);    // C style
using PF = void (*)(double);    // using plus C-style type
using P = [](double)->void; // using plus suffix return type, syntax error
using P = auto(double)->void // Fixed thanks to DyP

C ++ 11 이전의 using키워드는 멤버 함수를 범위로 가져올 수 있습니다. C ++ 11에서는 이제 생성자에 대해이 작업을 수행 할 수 있습니다 (다른 Bjarne Stroustrup 예제).

class Derived : public Base { 
public: 
    using Base::f;    // lift Base's f into Derived's scope -- works in C++98
    void f(char);     // provide a new f 
    void f(int);      // prefer this f to Base::f(int) 

    using Base::Base; // lift Base constructors Derived's scope -- C++11 only
    Derived(char);    // provide a new constructor 
    Derived(int);     // prefer this constructor to Base::Base(int) 
    // ...
}; 

Ben Voight는 새로운 키워드 나 새로운 구문을 도입하지 않는 이유 뒤에 꽤 좋은 이유를 제공합니다. 표준은 가능한 한 오래된 코드를 손상시키지 않으려 고합니다. 이것이 제안서 문서 Impact on the Standard에서 Design decisions,과 같은 섹션을 볼 수있는 이유이며 이전 코드에 미치는 영향입니다. 제안이 정말 좋은 아이디어처럼 보이지만 구현하기가 너무 어렵거나 너무 혼란 스럽거나 이전 코드와 모순되기 때문에 견인력이 없을 수있는 상황이 있습니다.


다음은 2003 n1449 의 오래된 논문입니다 . 근거는 템플릿과 관련된 것 같습니다. 경고 : PDF에서 복사하여 오타가있을 수 있습니다.

먼저 장난감 예를 살펴 보겠습니다.

template <typename T>
class MyAlloc {/*...*/};

template <typename T, class A>
class MyVector {/*...*/};

template <typename T>

struct Vec {
typedef MyVector<T, MyAlloc<T> > type;
};
Vec<int>::type p; // sample usage

이 관용구의 근본적인 문제와이 제안에 대한 주된 동기는 관용구로 인해 템플릿 매개 변수가 추론 할 수없는 컨텍스트로 표시된다는 것입니다. 즉, 템플릿 인수를 명시 적으로 지정하지 않으면 아래의 foo 함수를 호출 할 수 없습니다.

template <typename T> void foo (Vec<T>::type&);

따라서 구문이 다소 추합니다. 우리는 중첩을 피하는 ::type편이 낫습니다. 우리는 다음과 같은 것을 선호합니다.

template <typename T>
using Vec = MyVector<T, MyAlloc<T> >; //defined in section 2 below
Vec<int> p; // sample usage

"typedef 템플릿"이라는 용어는 특별히 피하고 혼동을 피하기 위해 "using"과 "="쌍을 포함하는 새로운 구문을 도입했습니다. 여기서는 어떤 유형도 정의하지 않습니다. 다음에 대한 동의어 (즉, 별칭)를 도입합니다. 템플릿 매개 변수를 포함하는 유형 ID (즉, 유형 표현식)의 추상화. 유형 표현식의 추론 가능한 컨텍스트에서 템플릿 매개 변수가 사용되는 경우 템플릿 별칭이 템플릿 ID를 형성하는 데 사용될 때마다 해당 템플릿 매개 변수의 값을 추론 할 수 있습니다. 이에 대한 자세한 내용은 다음과 같습니다. 어쨌든 이제 Vec<T>추론 가능한 컨텍스트에서 작동하는 일반 함수를 작성할 수 있으며 구문도 개선되었습니다. 예를 들어 foo를 다음과 같이 다시 작성할 수 있습니다.

template <typename T> void foo (Vec<T>&);

We underscore here that one of the primary reasons for proposing template aliases was so that argument deduction and the call to foo(p) will succeed.


The follow-up paper n1489 explains why using instead of using typedef:

It has been suggested to (re)use the keyword typedef — as done in the paper [4] — to introduce template aliases:

template<class T> 
    typedef std::vector<T, MyAllocator<T> > Vec;

That notation has the advantage of using a keyword already known to introduce a type alias. However, it also displays several disavantages among which the confusion of using a keyword known to introduce an alias for a type-name in a context where the alias does not designate a type, but a template; Vec is not an alias for a type, and should not be taken for a typedef-name. The name Vec is a name for the family std::vector< [bullet] , MyAllocator< [bullet] > > – where the bullet is a placeholder for a type-name. Consequently we do not propose the “typedef” syntax. On the other hand the sentence

template<class T>
    using Vec = std::vector<T, MyAllocator<T> >;

can be read/interpreted as: from now on, I’ll be using Vec<T> as a synonym for std::vector<T, MyAllocator<T> >. With that reading, the new syntax for aliasing seems reasonably logical.

I think the important distinction is made here, aliases instead of types. Another quote from the same document:

An alias-declaration is a declaration, and not a definition. An alias- declaration introduces a name into a declarative region as an alias for the type designated by the right-hand-side of the declaration. The core of this proposal concerns itself with type name aliases, but the notation can obviously be generalized to provide alternate spellings of namespace-aliasing or naming set of overloaded functions (see ✁ 2.3 for further discussion). [My note: That section discusses what that syntax can look like and reasons why it isn't part of the proposal.] It may be noted that the grammar production alias-declaration is acceptable anywhere a typedef declaration or a namespace-alias-definition is acceptable.

Summary, for the role of using:

  • template aliases (or template typedefs, the former is preferred namewise)
  • namespace aliases (i.e., namespace PO = boost::program_options and using PO = ... equivalent)
  • the document says A typedef declaration can be viewed as a special case of non-template alias-declaration. It's an aesthetic change, and is considered identical in this case.
  • bringing something into scope (for example, namespace std into the global scope), member functions, inheriting constructors

It cannot be used for:

int i;
using r = i; // compile-error

Instead do:

using r = decltype(i);

Naming a set of overloads.

// bring cos into scope
using std::cos;

// invalid syntax
using std::cos(double);

// not allowed, instead use Bjarne Stroustrup function pointer alias example
using test = std::cos(double);

참고URL : https://stackoverflow.com/questions/20790932/what-is-the-logic-behind-the-using-keyword-in-c

반응형