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에서 using
사용되는 키워드 type alias
는와 동일합니다 typedef
.
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 typedef to make `PFD` a pointer to a function returning void and accepting double
using PF = void (*)(double); // `using`-based equivalent of the typedef above
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 template”라는 용어를 구체적으로 피하고 혼동을 피하기 위해 “using”과 “=”쌍을 포함하는 새로운 구문을 도입합니다. 여기서는 어떤 유형도 정의하지 않고, 템플릿 파라미터를 포함하는 타입 -ID (즉, 타입 표현)의 추상화 템플릿 표현식이 형식 표현식의 해석 가능한 컨텍스트에서 사용되는 경우 템플릿 별칭을 사용하여 템플릿 ID를 형성 할 때마다 해당 템플릿 매개 변수의 값을 추론 할 수 있습니다. 이에 대한 자세한 내용은 다음과 같습니다. 어쨌든, 이제는
Vec<T>
추론 가능한 컨텍스트에서 작동하는 일반 함수를 작성할 수 있으며 구문도 개선되었습니다. 예를 들어 foo를 다음과 같이 다시 작성할 수 있습니다.template <typename T> void foo (Vec<T>&);
여기서는 템플릿 별칭을 제안하는 주된 이유 중 하나가 인수 공제 및 호출
foo(p)
이 성공 하기위한 것임을 강조합니다 .
후속 문서 n1489 는 다음 using
을 사용하는 대신 이유 를 설명합니다 typedef
.
템플릿 별명을 소개하기 위해 논문 [4]에서와 같이 키워드 typedef를 (재) 사용하는 것이 좋습니다.
template<class T> typedef std::vector<T, MyAllocator<T> > Vec;
이 표기법은 유형 별칭을 소개하는 것으로 이미 알려진 키워드를 사용하는 이점이 있습니다. 그러나 별칭이 형식을 지정하지 않고 템플릿을 지정하는 컨텍스트에서 형식 이름에 대한 별칭을 도입하는 것으로 알려진 키워드를 사용하는 혼동을 일으키는 몇 가지 혼란스러운 내용도 표시됩니다.
Vec
은 유형의 별칭이 아니며 typedef-name에는 사용하지 않아야합니다. 이름Vec
은 가족의 이름입니다.std::vector< [bullet] , MyAllocator< [bullet] > >
여기서 글 머리표는 type-name의 자리 표시 자입니다. 결과적으로 우리는 “typedef”구문을 제안하지 않습니다. 반면에 문장template<class T> using Vec = std::vector<T, MyAllocator<T> >;
다음과 같이 읽거나 해석 할 수 있습니다. 이제부터
Vec<T>
의 동의어로 사용할 것std::vector<T, MyAllocator<T> >
입니다. 그 독서를 통해 앨리어싱에 대한 새로운 구문은 합리적으로 논리적으로 보입니다.
s 유형 대신 별명 es 가 중요한 차이점이라고 생각합니다 . 동일한 문서에서 다른 인용문 :
별명 선언은 정의가 아니라 선언입니다. alias- 선언은 선언의 오른쪽에 지정된 유형의 별칭으로 선언 영역에 이름을 도입합니다. 이 제안의 핵심은 형식 이름 별칭과 관련이 있지만 네임 스페이스 별칭 또는 오버로드 된 함수의 이름 지정 집합에 대한 대체 철자를 제공하도록 표기법을 분명히 일반화 할 수 있습니다 (자세한 내용은 ✁ 2.3 참조). [ My note :이 섹션에서는 해당 구문의 모양과 제안에 포함되지 않은 이유에 대해 설명합니다. ] 문법 정의 별명 선언은 typedef 선언 또는 네임 스페이스 별명 정의가 허용되는 모든 곳에서 허용됩니다.
역할에 대한 요약 using
:
- 템플릿 별명 (또는 템플릿 typedef, 전자는 이름이 선호 됨)
- 네임 스페이스 별칭 (즉,
namespace PO = boost::program_options
과using PO = ...
동일) - 문서는 말합니다
A typedef declaration can be viewed as a special case of non-template alias-declaration
. 그것은 미학적 변화이며,이 경우 동일하다고 간주됩니다. - 범위 (예 :
namespace std
전역 범위), 멤버 함수, 상속 생성자에 무언가 가져 오기
그것은 할 수 사용할 수 :
int i;
using r = i; // compile-error
대신 다음을 수행하십시오.
using r = decltype(i);
과부하 세트의 이름을 지정합니다.
// 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);