2017-05-18 2 views
1

이전에 나는 question에 대해 std::variant이라고 물었다. 변형에 의해 보유 된 유형이 모두 std::cout에 의해 인쇄 가능한 것을 고려하면 방문자를 구현하는 간단한 방법이 있습니까?템플릿이 std :: variant의 방문을 위해 작동합니까?

Here 예를 들어, 모든 유형의 모든 람다를 처리 할 수 ​​있지만 모두 동일한 작업을 수행합니다 (std::string 제외) : std::cout << arg << ' ';. 내 자신을 반복하지 않는 방법이 있습니까?

std::visit(overloaded { 
      [](int arg) { std::cout << arg; }, 
      [](long arg) { std::cout << arg; }, 
      [](double arg) { std::cout << arg; } 
      // I removed the std::string case 
     }, v); // v is the std::variant 

대신 쓰기 :

std::visit( [](auto arg) { std::cout << arg; }, v); 

또는 뭔가 같은 :

template<typename T> 
void printer(T arg) {std::cout << arg; } 
//....... 
std::visit(printer, v); 
+2

두 번째 블록 (일반 람다 포함)이 작동해야합니다. 템플릿이 단일 함수 또는 객체가 아니기 때문에 세 번째 블록 (템플릿 함수 사용)은 작동하지 않습니다. 당신은 템플릿'operator()'로 당신 자신의 callable을 작성할 수 있습니다 : struct printer {template void operator() (T arg) {std :: cout << arg; }}; std :: visit (printer {}, v);'(일반적인 람다와 대략 동일합니다). –

+6

질문에 [tag : C++] 태그를 계속 추가 할 때 이유가 있습니다. 앞으로도 직접하십시오. –

답변

2

필요 없음이 (전달) 참조 arg 소요

std::visit( [](auto&& arg) { std::cout << arg; }, v); 

복사합니다. 나는 그것을 전달하는 것을 괴롭히지 않는다; 나는 그것이 정말로 rvalue 또는 lvalue인지 상관하지 않습니다.

방문자가 개체를 필요로하고 템플릿 함수가 함수의 개체가 아니기 때문에 템플릿 함수가 작동하지 않습니다. 오버로드 세트 이름을 C++에서 객체로 전달할 수는 없습니다.

overload 트릭은 주로 다른 행동을 파견하려는 경우입니다. 당신이 할 수있는

한 가지는 우리가 얻을 다음

template<typename T> 
void printer(T arg) {std::cout << arg; } 

std::visit([](auto&&arg){printer(arg);}, v); 

또는

#define RETURNS(...) \ 
    noexcept(noexcept(__VA_ARGS__)) \ 
    -> decltype(__VA_ARGS__) 

#define OVERLOADS_OF(...) \ 
    [](auto&&...args) \ 
    RETURNS(__VA_ARGS__(decltype(args)(args)...)) \ 
    { return __VA_ARGS__(decltype(args)(args)...); } 

입니다 :에 의해 이름이 지정된 함수의 과부하 세트를 나타냅니다 익명 객체를 생성

template<typename T> 
void printer(T arg) {std::cout << arg; } 

std::visit(OVERLOADS_OF(printer), v); 

토큰은 printer입니다.

+0

람다 본문을 잊어 버렸고 첫 번째 선언 유형 뒤에 여분의')'가 있습니다. – 0x499602D2

관련 문제