C ++에서 함수 이름에 별칭을 어떻게 할당합니까?


100

유형, 변수 또는 네임 스페이스의 새 이름을 만드는 것은 쉽습니다. 하지만 함수에 새 이름을 어떻게 할당합니까? 예를 들어, 내가 이름을 사용하려는 holler위해 printf. #define은 분명합니다 ... 다른 방법은 없나요?

해결책 :

  1. #define holler printf
  2. void (*p)() = fn; //function pointer
  3. void (&r)() = fn; //function reference
  4. inline void g(){ f(); }

여러분 모두 감사합니다. 내 동료는거야 사랑이보고있는 void (&NewName)(some_vector&, float, float, float, float) = OldName;내 옆에 체크합니다.
아넬 쿠 리안

19
표준 라이브러리 함수에 임의의 이름을 사용하는 것을보고 싶지는 않습니다.
jalf 2013-06-16

2
나는 printf여기서 엉망이 아닙니다 . 그것은 단지 예일뿐입니다. 여기서 문제는 다른 무엇보다 영어의 한계와 더 관련이 있습니다. 목적 A와 목적 B를 제공하는 단일 기능이 있지만 여기서 두 가지 목적을 모두 제공하는 단일 이름을 찾을 수 없습니다.
Agnel Kurian

2
@Neil, 정확하게. T &a = b;에 대한 새 이름을 만듭니다 b. typedef유형 및 namespace A=B;네임 스페이스에 대해.
Agnel Kurian

2
있다 using BaseClass::BaseClassMethod,있다 using AliasType = Type;, 심지어있다 namespace AliasNamespace = Namespace;. 우리가 누락 것은using AliasFunction = Function;
anton_rh

답변:


114

다양한 접근 방식이 있습니다.

  • 템플릿이 아닌 오버로드되지 않은 함수가있는 C ++ 11에서는 다음을 간단히 사용할 수 있습니다.

    const auto& new_fn_name = old_fn_name;
  • 이 함수에 여러 오버로드가있는 경우 다음을 사용해야합니다 static_cast.

    const auto& new_fn_name = static_cast<OVERLOADED_FN_TYPE>(old_fn_name);

    예 : 함수의 과부하가 두 개 있습니다. std::stoi

    int stoi (const string&, size_t*, int);
    int stoi (const wstring&, size_t*, int);

    첫 번째 버전에 별칭을 만들려면 다음을 사용해야합니다.

    const auto& new_fn_name = static_cast<int(*)(const string&, size_t*, int)>(std::stoi);

    참고 : 오버로드 된 모든 버전이 작동하도록 오버로드 된 함수에 별칭을 만들 수있는 방법이 없으므로 원하는 정확한 함수 오버로드를 항상 지정해야합니다.

  • C ++ 14를 사용하면 constexpr템플릿 변수 로 훨씬 더 나아갈 수 있습니다 . 이를 통해 템플릿 함수의 별칭을 지정할 수 있습니다.

    template<typename T>
    constexpr void old_function(/* args */);
    
    template<typename T>
    constexpr auto alias_to_old = old_function<T>;
  • 또한 C ++ 11부터는 std::mem_fn 멤버 함수의 별칭을 지정할 수 . 다음 예를 참조하십시오.

    struct A {
       void f(int i) {
          std::cout << "Argument: " << i << '\n';
       }
    };
    
    
    A a;
    
    auto greet = std::mem_fn(&A::f); // alias to member function
    // prints "Argument: 5"
    greet(a, 5); // you should provide an object each time you use this alias
    
    // if you want to bind an object permanently use `std::bind`
    greet_a = std::bind(greet, a, std::placeholders::_1);
    greet_a(3); // equivalent to greet(a, 3) => a.f(3);

1
좋습니다. C ++ 98은 어떻습니까? 설정 및 재설정에 사용되는 "재설정"과부하가있는 클래스가 있습니다. 내부적으로는 문제 없습니다. 외부 사용자의 경우 "set"으로 별칭을 지정하여 컨텍스트에 대해 직관적입니다 (기본 구성, clear () 'd 등 설정, 작업 개체 재설정). 클래스 메서드 : (1) "void (& set) (const string &, const bool, const bool);" (2) void (& set) (const string &, const int, const bool); 해당 서명이있는 2 개의 "리셋"이 작업을 수행합니다. 클래스 선언에 서명이 있으므로 class-initialize, : set (reset), set (reset). 그렇지 않은 경우 명시 적 static_cast 예제가 작동합니까?
Luv2code

8
constexpr템플릿 변수 접근 방식에 문제가있는 것 같습니다 . 별칭은 유형 추론을 수행 할 수 없습니다. 컴파일러에서 템플릿 매개 변수 목록을 제공해야합니다 (가변 템플릿 함수를 작성 중입니다) : 템플릿 인수 목록없이 변수 템플릿`alias_to_old '를 참조 할 수 없습니다
user69818

1
constexpr auto new_fn_name = old_fn_nameC ++ 11 (적어도 gcc 4.9.2에서)에서 작동하며 &. 항상 포인터를 통해 호출을 수행 할 필요가 없으므로 호출 대신 함수를 인라인 할 수 있습니다.
ony

C ++ 14 일반 람다를 사용하여 다음을 수행 할 수있었습니다. 대상 함수에 여러 오버로드가있을 때도 작동해야합니다. constexpr auto holler = [] ( auto &&...args ) { return printf( std::forward<decltype(args)>( args )... ); };
Anthony Hall

1
사용 std::mem_fn은 감각 뒤에 훨씬 더 많은 마술을 수행하기 때문에 별칭 이 아닙니다 .
cgsdfc

35

함수 포인터 또는 함수 참조를 만들 수 있습니다.

void fn()
{
}

//...

void (*p)() = fn;//function pointer
void (&r)() = fn;//function reference

2
케이크가 필요합니다. 함수 참조에 대해 몰랐습니다.
Agnel Kurian

@Vulcan : 둘 다 동일한 구문으로 호출 할 수 있다는 점에서 거의 동일하지만 주소가 약간 다릅니다. r은 주소를 보유하는 자체 메모리 공간을 차지하지 않습니다.
Brian R. Bondy 2010-06-16

1
fn별칭을 사용하여을 어떻게 호출 하시겠습니까? 함수 포인터와 함수 참조를 설명해 주시겠습니까? 어떻게 다릅니 까? 여기서도 똑같은가요?
ma11hew28

1
@Matt, fn이라고 부르는 것과 똑같이 부르십시오. r();
Agnel Kurian 2012-06-28

인스턴스 메소드에 대해이 작업을 어떻게 수행합니까? 편집 : 컴파일 된 것 같습니다 :void (&r)() = this->fn;
Sam

21
typedef int (*printf_alias)(const char*, ...);
printf_alias holler = std::printf;

잘해야합니다.


printf가 전역 네임 스페이스에 있지 않습니까?
Agnel Kurian 2013 년

3
당신이 포함 된 경우 글로벌의 <STDIO.H는>하지만 표준에 당신이 포함 된 경우 <cstdio>
Injektilo

@einpoklum : decltype 에는 아무런 문제가 없지만 대답은 2010 년부터입니다. 그 decltype당시에는 C ++ 11에서 소개 된 것처럼 없었 습니다. 좋은 오래된 일반 C.와 또한이해야 또한 작업
Phidelux


7

인라인 래퍼를 사용하십시오. 두 API를 모두 얻지 만 단일 구현을 유지합니다.


3

가입일 fluentcpp : ALIAS_TEMPLATE_FUNCTION의 (f, g)

#define ALIAS_TEMPLATE_FUNCTION(highLevelF, lowLevelF) \
template<typename... Args> \
inline auto highLevelF(Args&&... args) -> decltype(lowLevelF(std::forward<Args>(args)...)) \
{ \
    return lowLevelF(std::forward<Args>(args)...); \
}

1

C ++ 14 제네릭 람다를 사용하여 다음을 수행 할 수 있었으며 대상 함수에 여러 오버로드가있을 때도 작동합니다.

constexpr auto holler = [] ( auto &&...args ) {
        return printf( std::forward<decltype(args)>( args )... );
    };

하! 그것은 나를 슬프게합니다. 글쎄, 여기 나 한테 하나 먹어
FeRD

0

여기서 IMO를 언급 할 가치가 있습니다. 원래 질문 (및 훌륭한 답변)은 함수의 이름을 바꾸고 싶을 때 확실히 유용하지만 (그럴만 한 이유가 있습니다!), 원하는 모든 것이 깊은 네임 스페이스를 제거하는 것입니다. 이름을 유지하십시오. 이에 대한 using키워드가 있습니다.

namespace deep {
  namespace naming {
    namespace convention {
      void myFunction(int a, char b) {}
    }
  }
}
int main(void){
  // A pain to write it all out every time
  deep::naming::convention::myFunction(5, 'c');

  // Using keyword can be done this way
  using deep::naming::convention::myFunction;
  myFunction(5, 'c');  // Same as above
}

또한 항상 파일의 최상위 수준에서 사용할 수 있지만 범위로 제한된다는 장점이 있습니다. 나는 종종이를 사용 cout하고 endl내가 모두 동원 할 필요가 없습니다 std고전과 using namespace std;당신이 좋아하는 뭔가를 사용하는 경우 파일의 상단에,뿐만 아니라 유용std::this_thread::sleep_for() 하나 개의 파일이나 기능에 많은,하지만 모든 곳에서, 그리고 네임 스페이스의 다른 함수가 아닙니다. 항상 그렇듯이 .h 파일에서 사용하지 않는 것이 좋습니다. 그렇지 않으면 전역 네임 스페이스가 오염됩니다.

이것은 위의 "이름 변경"과 동일하지 않지만 종종 실제로 원하는 것입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.