가변 템플릿의 맥락에서“…”토큰에 대한 규칙은 무엇입니까?


98

C ++ 11에는 다음과 같은 가변 템플릿이 있습니다.

template< class T, class... Args >
unique_ptr<T> make_unique( Args&&... args )
{
    return unique_ptr<T>(new T(std::forward<Args>(args)...));
}

약간의 호기심이에 대해 다음과 같습니다 표현이 std::forward<Args>(args)...모두 사용 Args하고 args있지만, 단 하나의 ...토큰. 또한 std::forward하나의 템플릿 매개 변수와 하나의 인수 만 취하는 비가 변 템플릿 함수입니다. 이에 대한 구문 규칙은 무엇입니까 (대략)? 어떻게 일반화 할 수 있습니까?

또한 : 함수 구현에서 줄임표 ( ...)는 관심있는 표현의 끝에 있습니다. 템플릿 인수 목록과 매개 변수 목록에서 줄임표가 중간에있는 이유가 있습니까?


2
두 번째 부분에 대해 간단히 설명합니다. 템플릿 매개 변수 팩 또는 함수 매개 변수 팩을 "선언"할 때이 ...식별자가 도입되기 전에옵니다. 하나 또는 두 유형의 팩을 사용하는 경우 ...확장 할 표현식 패턴 뒤에옵니다.
aschepler 2013-07-15

답변:


99

가변 템플릿 컨텍스트에서 줄임표 ...는 템플릿 매개 변수 팩이 표현식의 오른쪽에 나타나면 압축을 푸는 데 사용됩니다 (이 표현식 패턴 을 잠시 호출하십시오 ). 규칙은 의 왼쪽에있는 패턴...반복 된다는 것입니다 . 압축을 푼 패턴 ( 지금 표현식 이라고 부름 )은 쉼표로 구분 ,됩니다.

몇 가지 예를 통해 가장 잘 이해할 수 있습니다. 이 함수 템플릿이 있다고 가정합니다.

template<typename ...T>
void f(T ... args) 
{
   g( args... );        //pattern = args
   h( x(args)... );     //pattern = x(args)
   m( y(args...) );     //pattern = args (as argument to y())
   n( z<T>(args)... );  //pattern = z<T>(args)
}

이제이 함수를 T로 전달 하여 호출하면 {int, char, short}각 함수 호출이 다음과 같이 확장됩니다.

g( arg0, arg1, arg2 );           
h( x(arg0), x(arg1), x(arg2) );
m( y(arg0, arg1, arg2) );
n( z<int>(arg0), z<char>(arg1), z<short>(arg2) );

게시 한 코드 std::forward에서 n()함수 호출에 표시된 네 번째 패턴을 따릅니다 .

x(args)...y(args...)위 의 차이점에 유의하십시오 !


다음 ...과 같이 배열을 초기화하는 데 사용할 수도 있습니다.

struct data_info
{
     boost::any  data;
     std::size_t type_size;
};

std::vector<data_info> v{{args, sizeof(T)}...}; //pattern = {args, sizeof(T)}

다음으로 확장됩니다.

std::vector<data_info> v 
{ 
   {arg0, sizeof(int)},
   {arg1, sizeof(char)},
   {arg2, sizeof(short)}
};

public다음 예제와 같이 패턴에와 같은 액세스 지정자가 포함될 수도 있음을 깨달았습니다 .

template<typename ... Mixins>
struct mixture : public Mixins ...  //pattern = public Mixins
{
    //code
};

이 예에서 패턴은 다음과 같이 확장됩니다.

struct mixture__instantiated : public Mixin0, public Mixin1, .. public MixinN  

즉, 모든 기본 클래스 mixture에서 공개적으로 파생됩니다 .

도움이 되었기를 바랍니다.


1
일치하는 표현에 관하여; 그것은해야 가능한 가장 큰 그것을해야하지, 표현? 예를 들어 x+args...에 확장해야 x+arg0,x+arg1,x+arg2하지 x+arg0,arg1,arg2.
비트 마스크

따라서 ...패턴의 모든 확장 가능한 엔티티에 적용됩니다.
밝기 경주 궤도에

@bitmask : 예. x+args...에 확장해야한다 x+arg0,x+arg1,x+arg2, 하지 x+arg0,arg1,arg2 .
Nawaz 2013

1
@ Jarod42 : C ++ 17이 출시되면이 답변을 업데이트하겠습니다.
Nawaz 2015

3
@synther : sizeof...(T)거기에 필요하지 않습니다. 당신은 단순히 쓸 수 있습니다 :int a[] = { ___ };
나와 즈

48

다음은 GoingNative 2012에서 Andrei Alexandrescu의 "Variadic Templates are Funadic" 강연에서 발췌 한 것입니다. 가변 템플릿에 대한 좋은 소개를 위해 추천 할 수 있습니다.


가변 팩으로 할 수있는 일은 두 가지가 있습니다. sizeof...(vs)요소 수를 가져와 확장하기 위해 신청할 수 있습니다.

확장 규칙

Use            Expansion

Ts...          T1, ..., Tn
Ts&&...        T1&&, ..., Tn&&
x<Ts,Y>::z...  x<T1,Y>::z, ..., x<Tn,Y>::z
x<Ts&,Us>...   x<T1&,U1>, ..., x<Tn&,Un>
func(5,vs)...  func(5,v1), ..., func(5,vn)

확장은 안쪽으로 바깥쪽으로 진행됩니다. 잠금 단계에서 두 목록을 확장 할 때는 크기가 같아야합니다.

더 많은 예 :

gun(A<Ts...>::hun(vs)...);

Ts의 템플릿 인수 목록에서 모두 를 확장 A한 다음 함수 hun가 all으로 확장됩니다 vs.

gun(A<Ts...>::hun(vs...));

Ts의 템플릿 인수 목록에서 Aall 및 all vs의 함수 인수로 모두 확장합니다 hun.

gun(A<Ts>::hun(vs)...);

기능 확장 hunTsvs로크 단계.

노트 :

Ts유형 vs이 아니며 값이 아닙니다! 유형 / 값 목록의 별칭입니다. 두 목록 중 하나가 비어있을 수 있습니다. 둘 다 특정 행동에만 순종합니다. 따라서 다음은 불가능합니다.

typedef Ts MyList;  // error!
Ts var;             // error!
auto copy = vs;     // error!

확장 궤적

함수 인수

template <typename... Ts>
void fun(Ts... vs)

이니셜 라이저 목록

any a[] = { vs... };

기본 지정자

template <typename... Ts>
struct C : Ts... {};
template <typename... Ts>
struct D : Box<Ts>... { /**/ };

멤버 이니셜 라이저 목록

// Inside struct D
template <typename... Us>
D(Us... vs) : Box<Ts>(vs)... {}

임시 인수 목록

std::map<Ts...> m;

인수와 일치 할 수있는 경우에만 컴파일됩니다.

목록 캡처

template <class... Ts> void fun(Ts... vs) {
    auto g = [&vs...] { return gun(vs...); }
    g();
}

속성 목록

struct [[ Ts... ]] IAmFromTheFuture {};

사양에 있지만 유형으로 표현할 수있는 속성은 아직 없습니다.


좋은. 함수 인수는 loci에서 제외되지만 : P
Potatoswatter

@Potatoswatter 감사합니다. 함수 인수 목록의 확장은 언급되지 않았습니다.
typ1232

@ typ1232 편집해서 죄송 합니다만, 원래 게시물이 표절에 너무 가깝다고 느꼈습니다. Btw, 나는 또한 얼마 전에 그 이야기를 봤습니다.
Walter
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.