일반 유형으로 특정 유형의 STL 컨테이너


25

특정 유형의 컨테이너를 std::string매개 변수로 사용하는 함수를 만들 수있는 방법이 있습니까?

void foo(const std::container<std::string> &cont)
{
   for(std::string val: cont) {
      std::cout << val << std::endl;
   }
}

모든 유형의 stl 컨테이너에 대해 입력으로 호출합니까? 위처럼?

std::set<std::string> strset;
std::vector<std::string> strvec;
std::list<std::string> strlist;

foo(strset);
foo(strvec);
foo(strlist);

2
네, 템플릿 함수라고합니다. ;)
— Ulrich Eckhardt

2
종종 한 쌍의 반복자를 전달하는 것이 더 좋습니다 (각각 컨테이너의 시작과 끝을 나타냄). 반복자가 함수의 요구 사항을 충족하는 한, 어떤 유형의 컨테이너에서 얻은 것인지는 중요하지 않습니다 (종종 예외가 있습니다).
— 피터

답변:


21

컨테이너 유형에 대한 템플리트 템플리트 매개 변수 를 사용 foo하여 함수 템플리트를 작성할 수 있습니다 .

예 :

template<template<typename...> typename C>
void foo(const C<std::string> &cont)
{
   for(std::string val: cont) {
      std::cout << val << std::endl;
   }
}

라이브


더 일반화 할 수 있다고 생각합니다. 내 대답을 참조하십시오.
— theWiseBro

Lars의 답변 은 C 스타일 배열에서도 작동하기 때문에 더 좋습니다.
— Ayxan

1
@theWiseBro 네, 일반적으로 좋은 생각입니다. 그러나 OP는 특정 유형으로 사용하기를 원한다고 생각합니다 std::string.
— songyuanyao

3
@theWiseBro 정확하게. OP는 하나의 특정 유형으로 작동해야한다고 말했다 . 따라서 더 일반화하면 이점이 없습니다.
— 스 필러

1
@theWiseBro 나는 당신이 무슨 뜻인지 이해합니다. 나는 OP의 원래 의도에 대해 확신하지 못한다. OP에 설명해야 할 수도 있습니다. :)
— songyuanyao

6

foo다른 경우 에 과부하 를 원하느냐에 따라

// Doesn't participate in overload resolution when not applicable
template<typename Container, typename = std::enable_if_t<std::is_same_v<typename Container::value_type, std::string>>>
void foo(const Container &cont) {
   for(std::string val: cont) {
      std::cout << val << std::endl;
   }
}

// simpler
template<typename Container>
void foo(const Container &cont) {
   static_assert(std::is_same_v<typename Container::value_type, std::string>, "Container must contain std::string")
   for(std::string val: cont) {
      std::cout << val << std::endl;
   }
}

다음 std::is_same과 같은 다른 테스트를 사용 std::is_convertible하여 허용 할 수 있습니다.

std::vector<char *> c_strings;
foo(c_strings);

0

대신 반복자를 사용하는 것이 좋습니다. 중간 결과는 다음과 같습니다

template<typename Iter>
void foo(Iter begin, Iter end) {
  using T = decltype(*begin);
  std::for_each(begin, end, [] (cons T & t) {
    std::out << t << '\n';
  }
}

이제 호출 가능한 템플릿을 사용하십시오.

template<typename Iter, typename Callable>
void foo(Iter begin, Iter end, Callable & c) {
  std::for_each(begin, end, c);
}

우리는 STL이 이미 제공하는 것을 사용하는 법을 배웠습니다.


-1

@songyuanyao의 답변에 덧붙여서 다음과 같이 더 일반화 할 수 있다고 생각합니다.

template<template<typename...> typename C, typename ... D>
void foo(const C<D...> &cont)
{
   for(const auto& val: cont) {
      std::cout << val << std::endl;
   }
}

1
이것은 요소 유형을 std :: string으로 제한하지 않으므로 질문에 대답하지 않습니다.
— 사샤

@Sasha 이것은 std :: string에 고정되어 있지 않지만 더 일반화 된 것이 사실입니다. OP는 특정 유형을 사용하려고합니다. 오늘 그가 std :: string을 사용하고 있고 내일에 MyCustomString을 대신 사용하고 싶다고 가정 해보십시오. 그가 한곳에서 코드를 편집하기 만하면되기 때문에 유지하기가 쉽지 않습니까?
— theWiseBro

그러나 이것은로 제한하는 방법을 표시하지 않습니다 중 특히 "컨테이너 가지고 싶었던 querent - 표준 : : 문자열 또는 MyCustomString 요소 특정 유형을 ". 그대로 템플릿으로 발생하는 모든 유형을 허용하며 그 시점에서 단일 <typename C>에서 대신 템플릿을 지정하는 이유는 무엇입니까? 그것은 훨씬 간단하고 약간 더 일반화되어 있습니다-예를 들어 std :: string (일명 std :: basic_string <char>) 컨테이너로 가져 오지만 사용자 정의 구조체 MyCustomString은 사용하지 않으므로 완전히 일반적인 것은 아닙니다.
— 사샤

그리고 함수가 요소를 std :: string으로 예상하면 사용자가 std :: tuple <int, double, std :: nullptr_t>를 전달 하여 사용 및 유지 관리가 더 어려워집니다 .
— 사샤

@ 사샤 흠. 너의 의도를 알 겠어. 사실입니다. 고마워요!
— theWiseBro
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.