2013-03-15 2 views
0

저는 C++ 템플릿을 처음 사용합니다. 두 개의 다른 템플릿 클래스를 조작 할 수있는 함수 집합을 작성했습니다. 하나는 항상 가치에 의해 전달되어야하며, 다른 하나는 거대한 양의 데이터를 나타 내기 때문에 참조로 전달되어야합니다.c 템플릿 함수 매개 변수 유형 선택

다음은 단순화 된 예입니다. arg가 ref 타입으로 태그가 붙어 있다면, 함수 시그니처를 const ref로 가져 오도록 정의하고 싶습니다.

template<bool B, typename, typename T2> 
struct if_ {}; 

template<typename T1, typename T2> 
struct if_<true, T1, T2> { 
    typedef T1 type; 
}; 

template<typename T1, typename T2> 
struct if_<false, T1, T2> { 
    typedef T2 type; 
}; 

struct ByvalTypeTag {}; 
template<typename T> 
class Byval : public ByvalTypeTag 
{ 
    T somedata; 
}; 

struct ByrefTypeTag {}; 
template<typename T> 
class Byref : public ByrefTypeTag 
{ 
    T somedata; 
}; 

template<typename T> 
void myfunc(typename if_<std::is_base_of<ByrefTypeTag, T>::value, const T&, T>::type arg) 
{ 

} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    Byref<int> arg; 
    myfunc(arg); 
    return 0; 
} 

내가 오류는 다음과 같습니다

오류 C2783 : '무효 myfunc에 (있는 경우 _ :: 값, CONST T &, T> :: 형)': 'T'에 대한 템플릿 인수를 추론 할 수 없었다

어쩌면 이것이 잘못된 방법 일 것입니다. 가능하다면 동일한 기능을 위해 작성중인 상대적으로 중복되는 템플릿의 수를 줄이려고합니다.

+0

컴파일러는'myfunc'의 인수에서'T'을 추론 할 수 없습니다가, 식 (그리고 템플릿 인스턴스화를 통해 이전 버전과 유형을 infering하는 것은 일반적으로 중단 문제를 해결 필요할 수) 너무 복잡하다. ..당신은 타입을 명시 적으로'myfunc < Byref> (arg)'로 제공해야한다. (또는 누군가가 원하는 것을하기위한 다른 까다로운 방법을 찾을 수있다. 그러나 그것은 가장 직접적인 해결책이다.) –

답변

1

예, 컴파일러에서 유형을 추론 할 수 없습니다. 당신은 T 자신을 함께 제공해야합니다 :

class byref 
{ 
    typedef byref_tag tag; 
    ... 
}; 

template < typename T > 
void fun(T const& t, byref_tag) { ... } 

template < typename T > 
void fun(T t, byval_tag) { ... } 

template < typename T > 
void fun(T const& t) 
{ 
    typedef typename T::tag tag; 
    fun(t,tag()); 
} 

가 또 다른 대안은 래퍼 함수와 클래스 템플릿을 포함합니다 :
myfunc<ByRef<int>>(arg); 

은 또한 당신이 더 일반적인 태그 파견 시스템을 사용할 수 있습니다. 어느 쪽의 방법이라도 바깥 쪽의 기능은 ref에 의한 것이어야한다.

1

추론하지 않는 컨텍스트에서 T 유형을 추론하려고합니다.

매개 변수의 종속 형식에 이중 콜론이 있으면 일반적으로 매개 변수 형식을 추론 할 수 없다는 힌트를 제공합니다 (동일한 함수 호출에서 도움이되는 다른 추측 컨텍스트가없는 한 여기에서 당신은 단 하나의 논쟁 만 가지고 있습니다). 는 C++ 11 표준 조제 14.8.2.5/5에서

:

비 추론 문맥은 다음과 같습니다

- 사용하여 지정된 유형의 중첩 된 이름 지정 qualified-id.

당신이 구체적인 예를해야하는 경우

[...], this Q&A on StackOverflow는 꽤 좋은 일을 제공합니다. 이 경우에, 당신은 명시 적으로 형식 인수를 제공 할 수있다 :

myfunc<Byref<int>>(arg); 

또는 당신이 this second Q&A에서 제안 된 두 가지 해결 방법 중 하나를 선택할 수 있습니다.

+0

그래서 템플릿 함수 정의처럼 들릴 수있다. 유형을 감지하고 const &를 자동으로 추가합니다. 사용자가 템플릿을 수동으로 선택하지 않아도됩니다. –

0

이 구현으로 매개 변수를 전달할 수 있습니다.

template<typename T> 
void myfunc_impl(T arg) 
{ 
    // Do the work here. 
} 

template<typename T> 
void myfunc(const T &arg, typename std::enable_if<std::is_base_of<ByrefTypeTag, T>::value>::type* = 0) 
{ 
    myfunc_impl<const T&>(arg); // Pass a const ref 
} 

template<typename T> 
void myfunc(const T &arg, typename std::enable_if<std::is_base_of<ByvalTypeTag, T>::value>::type* = 0) 
{ 
    myfunc_impl<T>(arg);  // Pass a copy 
} 
+0

나는 이것과 비슷한 것을 가지고 있었지만, 나는 모든 중복 된 코드를 없애려고 노력했다. 두 위치 중 하나를 입력 할 수있는 2 항 연산자 함수의 경우 모든 조합이 필요합니다. 못생긴 종류의, 그래서 나는 뭔가 청소기를 바라고 있었다. –