3

적어도 하나의 인수를 취하여 모든 후속 인수의 thes 목록과 첫 번째 인수를 비교하는 inListi() 함수를 작성했습니다. 첫 번째 인수가 목록의 요소이면 true를 반환하고 그렇지 않으면 false를 반환합니다. 따라서 :변수 템플릿 함수를 다룰 때의 문제

if(inListi(1.2, 2.3, 4.5, 1.2)) 
    std::cout << "Returns true because last argument equals the first argument." << endl; 

if(inListi("hello", "world", "HEllo")) 
    std::cout << "This should print out because of the last argument." << endl; 

문제는 작동하지 않습니다. 아래 코드가 있습니다. char [N]의 경우 계속하기 전에 배열의 N 부분을 문자열로 복사합니다. null로 끝나는 char [N]을 전달할 수 있기 때문에이 작업을 수행하려고합니다.

어쨌든 코드는 다음과 같습니다. 대부분의 코드는 중복되어 있으며 const와 하나의 인수가 const [N]이고 다른 하나가 해당 유형이 아닌 조합을 처리합니다. (그건 그렇고,이 반복을 줄일 수있는 방법은 무엇입니까?)

#include <iostream> 
#include <stdexcept> 
#include <string> 
#include <sstream> 
#include <typeinfo> 
#include <type_traits> 

#include <boost/algorithm/string.hpp> 

using namespace std; 

//////////////////////////////////////////////////////////////////////////////// 
// inListi 
//////////////////////////////////////////////////////////////////////////////// 
template<typename T> 
bool inListi(T&& value) 
{ 
    return false; 
} 


template<typename FirstType, typename SecondType, typename ... Rest> 
bool inListi(FirstType&& first, SecondType&& second, Rest ... rest) 
{ 
    cout << "GENERIC inListi" << endl; 
    cout << "first is " << typeid(first).name() << endl; 
    cout << "second is " << typeid(second).name() << endl; 

    if(first == second) 
     return true; 
    else return inListi(first, rest...); 
} 


// We specialize the inListi for strings. We lower the case. 
// but what if char[n] is passed? We have specializations that 
// convert that to strings. 
template<typename ... Rest> 
bool inListi(string &&first, string &&second, Rest ... rest) { 
    string lFirst = first; 
    string lSecond = second; 

    cout << "LOWERED" << endl; 

    boost::algorithm::to_lower(lFirst); 
    boost::algorithm::to_lower(lSecond); 

    if(lFirst == lSecond) 
     return true; 
    else return inListi(first, rest...); 
} 



// Specializations for when we are given char-arrays. We copy the 
// the arrays into a string upto the size of the array. This is done 
// to take care of the case of when the char-array is not nul-terminated. 
// The amount repetition is to permutate over which argument is a char-array 
// and also for const-ness. 
template<int F, typename SecondType, typename ... Rest> 
bool inListi(char (&&first)[F], SecondType &&second, Rest ... rest) { 
    string strFirst = string(first, F); 
    cout << "arr, type, rest" << endl; 
    return inListi(strFirst, second, rest...); 
} 
template<int F, typename SecondType, typename ... Rest> 
bool inListi(const char (&&first)[F], SecondType &&second, Rest ... rest) { 
    string strFirst = string(first, F); 
    cout << "const arr, type, rest" << endl; 
    return inListi(strFirst, second, rest...); 
} 
template<typename FirstType, int S, typename ... Rest> 
bool inListi(FirstType &&first, char (&&second)[S], Rest ... rest) { 
    string strSecond = string(second, S); 
    cout << "type, arr, rest" << endl; 
    return inListi(first, strSecond, rest...); 
} 
template<typename FirstType, int S, typename ... Rest> 
bool inListi(FirstType &&first, const char (&&second)[S], Rest ... rest) { 
    string strSecond = string(second, S); 
    cout << "type, const arr, rest" << endl; 
    return inListi(first, strSecond, rest...); 
} 
template<int F, int S, typename ... Rest> 
bool inListi(char (&&first)[F], char (&&second)[S], Rest ... rest) { 
    string strFirst = string(first, F); 
    string strSecond = string(second, S); 
    cout << "arr, arr, rest" << endl; 
    return inListi(strFirst, strSecond, rest...); 
} 
template<int F, int S, typename ... Rest> 
bool inListi(const char (&&first)[F], char (&&second)[S], Rest ... rest) { 
    string strFirst = string(first, F); 
    string strSecond = string(second, S); 
    cout << "const arr, arr, rest" << endl; 
    return inListi(strFirst, strSecond, rest...); 
} 
template<int F, int S, typename ... Rest> 
bool inListi(char (&&first)[F], const char (&&second)[S], Rest ... rest) { 
    string strFirst = string(first, F); 
    string strSecond = string(second, S); 
    cout << "arr, const arr, rest" << endl; 
    return inListi(strFirst, strSecond, rest...); 
} 
template<int F, int S, typename ... Rest> 
bool inListi(const char (&&first)[F], const char (&&second)[S], Rest ... rest) { 
    string strFirst = string(first, F); 
    string strSecond = string(second, S); 
    cout << "const arr, const arr, rest" << endl; 
    return inListi(strFirst, strSecond, rest...); 
} 


int main() { 

    if(inListi("Hello", "World", "HEllo")) 
     cout << "Hello is in the listi." << endl; 
    else 
     cout << "Hello is not in the listi." << endl; 

    return 0; 
} 

프로그램의 출력은 다음과 같다 : 중간 코드 중 어느 것도, 그것을 호출되지 것을,

[bitdiot foo]$ g++ forStackOverflow.cpp -std=gnu++0x 
[bitdiot foo]$ ./a.out 
GENERIC inListi 
first is A6_c 
second is A6_c 
GENERIC inListi 
first is A6_c 
second is PKc 
Hello is not in the listi. 

공지 사항 제네릭 버전을 사용하여 바로갑니다. 또한, 이상하게 보이는 또 다른 것은 'PKc'입니다. 나는 char * 타입이라고 가정한다. 자, 왜 다른 타입일까요?

어쨌든 고맙습니다 !!

답변

2

const char* (아마도 PKc이 무엇을 의미하는지)에 과부하를 사용할 수있는 것처럼 보입니다.

아마 같은 :

template<typename ... Rest> 
bool inListi(const char *first, const char *second, Rest... rest) { 
    cout << "const char*, const char*, rest" << endl; 
    return inListi(string(first), string(second), rest...); 
} 

다른 두 가지 :

  • 참고 임시직의 사용은 우리는
  • const char* 과부하가 첫 번째 통화를 일치합니다 string&& 버전을 부를 것이다 있도록 후속 통화를 처리하기 위해 과부하가 더 필요할 수 있습니다.

또 다른 편집 : 이것은 한 모든 인수가 동일한 유형을 가지고 작동

#include <iostream> 
#include <string> 
#include <utility> 
#include <algorithm> 
#include <cctype> 

template <typename T> 
bool inListi(T&& value) 
{ 
    return false; 
} 

template <typename FirstType, typename SecondType, typename... Rest> 
bool inListi(FirstType&& first, SecondType&& second, Rest&&... rest) 
{ 
    if (first == second) 
    return true; 
    else 
    return inListi(std::forward<FirstType&&>(first), rest...); 
} 

template <int N, int M, typename... Rest> 
bool inListi(char (&first)[N], char (&second)[M], Rest&&... rest) 
{ 
    std::string lFirst(first, N); 
    std::transform(lFirst.begin(), lFirst.end(), lFirst.begin(), ::tolower); 
    std::string lSecond(second, M); 
    std::transform(lSecond.begin(), lSecond.end(), lSecond.begin(), ::tolower); 

    if (lFirst == lSecond) 
    return true; 
    else 
    return inListi(first, rest...); 
} 

template <typename... Rest> 
bool inListi(const char *first, const char *second, Rest&&... rest) 
{ 
    std::string lFirst(first); 
    std::transform(lFirst.begin(), lFirst.end(), lFirst.begin(), ::tolower); 
    std::string lSecond(second); 
    std::transform(lSecond.begin(), lSecond.end(), lSecond.begin(), ::tolower); 

    if (lFirst == lSecond) 
    return true; 
    else 
    return inListi(first, rest...); 
} 

int main() { 
    char a[5] = {'H','e','l','l','o'}; 
    char b[5] = {'W','o','r','l','d'}; 
    char c[5] = {'H','E','l','l','o'}; 
    std::cout << inListi(a, b, c) << '\n'; 
    std::cout << inListi("Hello", "World", "HEllo") << '\n'; 
    std::cout << inListi(5, 42, 5) << '\n'; 
} 

: prevent array decay in parameter pack expansion에서 탁월한 피드백이이 매개 변수 팩를 rvalue 참조를 사용하여 수행 할 수있는 방법을 우리에게 보여줍니다. 혼합 유형을 시작하려면 적절한 과부하 쌍을 모두 작성해야합니다.

+0

적시에 답변 해 주셔서 감사합니다. 두 개의 문자열 로컬 변수를 선언하고 첫 번째와 두 번째를 할당하여이 코드를 수정했습니다. 코드가 호출 되긴하지만 (string, string, rest) 코드는 이후에 호출되지 않고 일반 버전으로 점프됩니다. 따라서 to_lower 코드 (string, string, rest)는 결코 호출되지 않습니다. 어떤 제안? – Bitdiot

+0

(문자열, 문자열) 오버로드를 추가해보십시오. –

+0

다시 한번 감사드립니다. 원본 코드에서 (문자열, 문자열, 나머지) 버전이 있습니다. 그러나 나머지 (문자열, 문자열) 버전을 추가하고 여전히 일반 코드를 호출합니다. – Bitdiot

관련 문제