2010-03-28 6 views
4

int, double 및 문자열과 같은 특정 데이터 형식에서 작동하는 오버로드 된 함수가 있습니다. 이러한 함수의 대부분은 동일한 작업을 수행하며 특정 데이터 형식 집합 만 허용됩니다. 즉, 형식 안전성을 잃어 버리고 (함수 내에서 유효성 검사를 위해 잠재적으로 런타임 문제가 발생 함) 단순한 일반 템플릿 함수를 만들 수 없다는 것을 의미합니다.준 일반 함수

"semi-generic 컴파일 타임 유형 안전 기능"을 만들 수 있습니까? 그렇다면 어떻게? 그렇지 않다면 C++ 0x로 나타날 것입니까?

(유효하지 않은) 아이디어입니다.

template <typename T, restrict: int, std::string > 
void foo(T bar); 
... 
foo((int)0); // OK 
foo((std::string)"foobar"); // OK 
foo((double)0.0); // Compile Error 

참고 : 생성자와 할당 연산자가 오버로드 된 클래스를 생성하고 해당 클래스의 변수를 함수에 전달할 수 있다는 것을 알고 있습니다.

+1

. 또한 유형은 런타임에 확실히 확인되지 않습니다. – UncleBens

+0

UncleBens : 복식에 대한 위의 예제가 컴파일 될 때까지 "유형 안전성"이 없습니다. –

답변

5

사용 sfinae fooT에 대한 string 또는 int을 받아 들일 수있을 것입니다

template<typename> struct restrict { }; 
template<> struct restrict<string> { typedef void type; }; 
template<> struct restrict<int> { typedef void type; }; 

template <typename T> 
typename restrict<T>::type foo(T bar); 

그건 : 여기

일부 의사 코드 내 생각을 명확히한다. foo(0.f)을 호출하면 하드 컴파일 시간 오류가 발생하지 않지만 인수를 허용하는 다른 함수가있는 경우 대신 해당 인수가 사용됩니다.

+0

게시 된 코드는 VC++ 9에서도 컴파일되지 않습니다. (두 번째 줄의 "템플릿 인수가 너무 적음"[다른 오류 중] –

+0

코드를 편집 할 수 없지만 "struct restrict ..."전에 템플릿 <>을 추가하면이 작업이 수행됩니다. 템플릿 vodoo .. –

+0

죄송합니다, 내가 쓴 때 나는 자고있었습니다. –

1

외부에 노출되지 않는 "개인적인"templatized 함수를 만들어 "안전한"오버로드에서 호출 할 수 있습니다.

그런데 일반적으로 템플릿 화 된 버전을 직접 노출하면 문제가 발생합니다. 전달 된 유형이 적합하지 않은 경우 컴파일 오류가 발생합니다 (알고리즘이 일부 데이터 유형).

class foo { 
    void operator()(double); // disable double type 
public: 
    template<typename T> 
    void operator()(T bar) { 
     // do something 
    } 
}; 

void test() { 
    foo()(3); // compiles 
    foo()(2.3); // error 
} 

편집 :

+0

암시 적 변환을 고려해야합니다. 'foo (double)'과부하를 가지고 있지만 모든 정수형 등에 대해 사용을 중지하고자 할 때주의하십시오. – UncleBens

+0

아직 공개 함수를 유지해야하기 때문에별로 도움이되지 않습니다. –

+0

@UncleBens : 네 말이 맞습니다[email protected] Ullner : 문제가 뭐니? .cpp (약간 다른 방식으로 호출하는 것)에서만 템플릿 버전을 만들고 .hpp (또는 .h)의 오버로드 만 다른 컴파일 단위에서 사용하도록 남겨 둡니다. –

0

아마 조금 못생긴 솔루션,하지만 펑은 옵션이 될 수 I 를 반전 내 솔루션

class foo { 
    template<typename T> 
    void operator()(T bar, void* dummy) { 
    // do something 
    } 
public: 
    // `int` is allowed 
    void operator()(int i) { 
     operator()(i, 0); 
    } 
}; 

foo()(2.3); // unfortunately, compiles 
foo()(3); // compiles 
foo()("hi"); // error 
+0

흥미로운 생각이지만, 그 중 하나는 유효하지 않은 모든 잠재적 인 데이터 유형을 생각할 필요가 있다는 것을 의미합니다. (실용적인) 무한 수가 있습니다. –

+0

@Fredrik, 네, 그게 문제입니다. 나는 나의 대답을 업데이트했다. –

0

당신은 아마 "제한에 대한 템플릿 전문으로 일할 수 "유형을 허용하고 싶습니다. 다른 모든 유형의 경우 템플릿 전문화 기능을 제공하지 않으므로 일반 "기본"템플릿이 사용됩니다. 여기서 BOOST_STATIC_ASSERT와 같은 것을 사용하여 컴파일 오류를 발생시킬 수 있습니다.

template <typename T> 
void foo(T bar) {BOOST_STATIC_ASSERT(FALSE);} 

template<> // specialized for double 
void foo(double bar) {do_something_useful(bar);}; 
+0

올바른 구문은 템플리트가 아닌 오버로드입니다. :) – UncleBens

+0

"typename : special for double"에 대한 적절한 문서를 찾을 수 없습니다. –

+0

'template <> void foo (double bar);'템플릿 함수를 특수화하지 않는 것이 좋습니다 : void foo (double bar); – UncleBens

0

유형 목록을 임의로 선택하려면 입력 목록을 사용할 수 있습니다. 예 : last part of my earlier answer 참조

사용법 뭔가처럼 될 수 있습니다 나는 제한이 다소 의심없이 당신이 유형의 안전을하지 않았을 가정을 생각

//TODO: enhance typelist declarations to hide the recursiveness 
typedef t_list<std::string, t_list<int> > good_for_foo; 

template <class T> 
typename boost::enable_if<in_type_list<T, good_for_foo> >::type foo(T t); 
관련 문제