템플릿을 사용하여 함수 오버로드


34

템플릿을 사용하여 함수를 정의하려고하는데 형식 이름이 int 또는 anEnum (정의 된 열거 형)이되고 싶습니다. 나는 다음을 시도했지만 실패했다.

template <int | anEnum T> // or <int T, anEnum T> or <int, anEnum T>
bool isFunction(const T &aVariable){}

내가하려고하는 것은 두 개의 오버로드 된 함수를 정의하는 대신 템플릿을 사용하는 것입니다. 프로그래머가 유형을 고려할 필요없이 함수를 다음과 같이 호출하는 것이 좋습니다.

isFunction(aVariable) // and not isFunction<int> (aVariable) nor isFunction<anEnum> (aVariable)

기본적 으로이 함수를 int 및 aNum 유형에 맞게 템플릿 화하고 싶습니다. 나는 이것을 찾았지만 답을 찾을 수 없었다. 무엇을 놓칠 수 있습니까? 감사합니다,


정확히 하나의 열거 형이거나 int 유형이라면 두 함수를 모두 작성하는 것이 어떻습니까? 이 경우 템플릿이 필요한 이유는 무엇입니까?
클라우스

다른 유형은 어떻습니까? false다른 유형 으로 돌아가 거나 다른 유형의 함수를 인스턴스화하지 않으려 고합니다.
frogatto

@frogatto 아니요, bool 반환 값에는 유형이 없습니다.
bg

@ 클라우스 나는 대안을 배우도록 요청했습니다. 현재 답변을 바탕으로 두 기능을 간단히 정의하기로 결정했습니다.
bg

답변:


25

C ++ 20이 아닌 답변 외에도 C ++ 20 과 그 concepts기능 을 사용할 수 있다면 다음과 같은 구현을 제안합니다.

#include <iostream>
#include <concepts>

enum class MyEnum {
    A,
    B,
    C
};

template <typename T>
concept IntegralOrEnum = std::same_as<MyEnum, T> || std::integral<T>;

template <IntegralOrEnum T>
bool isFunction(T const& aVariable) {
    return true;
}

int main() {
    isFunction(MyEnum::A);
    isFunction(3);
    isFunction("my_string"); // error
    return 0;
}

데모

최신 정보

@RichardSmith 의 의견 에 따르면 다음은 더 확장 가능하고 재사용 가능한 접근 방식입니다.

template <typename T, typename ...U>
concept one_of = (std::is_same_v<T, U> || ...);

template <one_of<int, MyEnum> T>
bool isFunction(T const& aVariable) {
    return true;
}

유형이 두 가지 유형 중 하나 여야하는 특정 사례의 경우 다음과 같이 더 효과적 일 수 있습니다.template<typename T, typename ...U> concept one_of = (std::is_same_v<T, U> || ...); template<one_of<int, MyEnum> T> bool isFunction(T const& aVariable) {
Richard Smith

1
@RichardSmith 나는 그것으로도 대답을 업데이트했습니다. 나는 이것을 더 재사용 가능하고 확장 가능하다는 것을 알았습니다. 감사합니다
NutCracker

21

이를 달성하기위한 몇 가지 방법이 있습니다. 모두 type_traits헤더를 사용합니다 . 예를 들어 함수 본문에서 해당 유형에 대해 정적 어설 션을 수행 할 수 있습니다.

또는 다른 과부하 중에서이 기능을 고려해야하는 경우 SFINAE 기술을 사용할 수 있습니다.

template<typename T>
auto isFunction(const T &aVariable) 
  -> std::enable_if_t<std::is_same<T, int>::value || std::is_same<T,anEnum>::value, bool> {
}

유형이 일치하지 않으면 호출되기 전에 과부하 세트에서 함수를 제거합니다. 그러나이 동작이 필요하지 않은 경우 정적 어설 션을 사용하면보다 프로그래머에게 친숙한 오류 메시지가 표시됩니다.


3

이 솔루션은 어떻습니까? 유형 T가 요구 사항을 충족하면 함수가 포함 된 코드가 컴파일됩니다. 그렇지 않으면 정적 어설 션이 실패했습니다.

#include <type_traits>
enum anEnum {
    //
};

template <typename T, bool defined = std::is_same<T, int>::value ||
                                     std::is_same<T, anEnum>::value>
bool isFunction(const T& aVariable)
{
    static_assert(defined, "Invalid specialization");

    bool result = false;
    // Put your code here
    return result;
}

1
다른 서명 (예 : 가상 isFunction(std::string_view)) 이있는 경우 과부하 해결에 적합하지 않습니다 . 서명은 여전히 ​​유효하지만 인스턴스화로 인해 오류가 발생합니다.
LF

쓸모없는 서명을 삭제 된 것으로 선언 할 수 있습니다. bool isFunction (std :: string_view) = delete;
ixjxk

추가 과부하에 대해 이야기하고 있습니다. 이 경우, 유효하지 않은이 서명은 (예를 들어, 문자열 리터럴의 경우) 정확히 일치하여 과부하를 차단할 수 있습니다.
LF

0

https://stackoverflow.com/a/60271100/12894563 답변을 개선했습니다 . 'constexpr'이이 상황에서 도움이 될 수 있다면 :

template <typename T>
struct always_false : std::false_type {};

template <typename T>
bool isFunction(const T& aVariable)
{
    if constexpr(std::is_same_v<T, int> || std::is_same_v<T, anEnum>)
    {
        std::cout << "int\n";
        // put your code here
        return true;
    }
    else
    {
        static_assert(always_false<T>::value, "You should declare non-template function or write if constexpr branch for your type");
        return false;
    }
}

bool isFunction(std::string_view)
{
    std::cout << "std::string_view\n";
    return true;
}

int main()
{
    isFunction(std::string_view("1L"));
    isFunction(1);
    //isFunction(1L); // will produce an error message from static_assert
}

과부하 된 기능이나 'if constexpr'분기가 없기 때문에 isFunction (1L)이 실패합니다.

업데이트 : 수정 누락

template <typename T>
struct always_false : std::false_type {};

https://godbolt.org/z/eh4pVn


static_assert(false, ...)사용되지 않은 잘못된 NDR입니다. 운이 좋으면 Clang처럼 godbolt.org/z/m_Gk9n
StoryTeller-Unslander Monica의

귀하의 의견에 감사드립니다. 실수했습니다. 고정, godbolt.org/z/eh4pVn
ixjxk
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.