2013-02-19 3 views
7
#include <functional> 

void f1(int) 
{} 

void f2(int, ...) 
{} 

int main() 
{ 
    std::function<void(int)>  g1 = f1; // OK. 
    std::function<void(int, ...)> g2 = f2; // Error! Not standard C++! 
} 

왜 C++ (11)는 전문 템플릿 클래스를 제공하지 않습니다 : 그 전문이 제공되지 않는 이유 궁극적 인 이유 (나는 것을 모르는)을 제공하는 것을 의미하지 않는다C++ 11이 'std :: function <void (int, ...)>'을 지원하지 않는 이유는 무엇입니까? 다음과 같이

template<class ResultType, class... ArgTypes> 
class function<ResultType(ArgTypes......)> 
{ 
    // ... ... ... 
}; 
+0

작동 여부를 확인하는 템플릿을 테스트 해 보셨습니까? – Omnifarious

+1

두 개의 스 니펫 모두 완전히 다른 것을 보여줍니다. Variadic 템플릿은 컴파일 할 때 처리됩니다. "C"스타일 변수 인수는 런타임에 처리됩니다. – mfontanini

+0

'...'(variadic 템플릿이 아님) 매개 변수 구문은 C와의 하위 호환성을 위해 유지됩니다. 사용법은 권장하지 않습니다. –

답변

5

, 하지만 어쩌면 나는 그것을 구현하려고 할 때 발생할 수있는 기술적 인 장애물에 대해 암시 할 수 있습니다. 그것은 당신에게 전문화가 왜 없는지에 대한 느낌을 줄 수 있기를 바랍니다.

먼저 std::function<> 클래스 템플릿 자체를 구현할 수있는 방법을 생각해 봅시다. 다음과 같이 설계의 기초가되는 유형의 삭제 방법은 (실제 구현 방법이 더 복잡 이것은 단지 예시 단순화입니다) 스케치 할 수 있습니다 :

#include <memory> 

template<typename T> 
struct function { }; 

template<typename R, typename... Args> 
struct function<R(Args...)> 
{ 

public: 

    template<typename F> 
    function(F&& f) : _holder(
     new holder<typename std::decay<F>::type>(std::forward<F>(f)) 
     ) 
    { } 

    R operator() (Args&&... args) 
    { _holder->call(std::forward<Args>(args)...); } 

private: 

    struct holder_base 
    { virtual R call(Args&&... args) = 0; }; 

    template<typename F> 
    struct holder : holder_base 
    { 
     holder(F&& f) : _f(std::forward<F>(f)) { } 
     R call(Args&&... args) { return _f(std::forward<Args>(args)...); } 
     F _f; 
    }; 

    std::unique_ptr<holder_base> _holder; 
}; 

을 이제 타원의 전문화가 실제로 어떻게 보이는지 확인해 보겠습니다 . 무엇보다도 variadic 함수에 제공되는 인수의 수와 유형은 이 아니며 해당 함수의 서명이이 아닙니다. 이것은 우리를 강제로

template<typename R, typename... Args> 
struct function<R(Args.......)> 
{ 
    ... 

    template<typename... Ts> 
    R operator() (Args&&... args, Ts&&... ts) 
    { _holder->call(std::forward<Args>(args)..., std::forward<Ts>(ts)...); } 

    ... 

, 차례로, holder<>의 호출 연산자 가변 인자 함수 템플릿 만들기 : 따라서, 우리의 전문 템플릿의 호출 연산자는 인수의 수와 종류를 받아들이는 함수 템플릿해야합니다. 그러나 형식 지우기를 실현하려면 동일한 호출 연산자가 virtual이어야하며 함수 템플릿은 C++에서 virtual이 될 수 없습니다.

variadic 인수 (여기서 생략 부호에 대해 말하고 있습니다.)는 가변적 인 템플릿 매개 변수와 완벽한 전달로 재귀하지 않고도 쉽게 전달할 수 있습니다. 나는 그것을 달성하는 간단한 방법을 알지 못한다. 특히 variadic list와 일치하는 인수가 아닌 다른 인수가 함수에 전달되지 않는다면 특히 그렇다.

+0

다른 접근법이 있다고 생각합니다. 하지만 그래, 그것을 구현의 기술적 도전은 내 머리를 다치게하고, 나는 그것이 깔끔하게 끝날 수 있는지 모르겠다. – Omnifarious

+0

가상 * 연산자() (Args ..., va_args vargs)'에'va_args' 객체를 전달하려고 시도한 다음 어떻게 든 그것을 '소유자'의 operator()에 확장하려고 시도 할 수 있습니다. ...그러나 나는 그것이 거친 엉망이 될 것이라고 생각한다. – Xeo