2015-01-27 3 views
2

Daniel Frey의 대답 덕분에 this post에 대한 답변 덕분에 같은 템플릿 매개 변수로 템플릿 클래스에 템플릿 friend 함수를 선언하는 방법을 알았습니다. 아쉽게도 추가 템플릿 매개 변수를 사용하여 친구 함수를 선언하는 구문은 여전히 ​​나를 벗어납니다.새 템플릿 매개 변수를 소개하는 템플릿 클래스의 템플릿 friend 함수

template <typename T> 
class Obj; 

template <typename T> 
Obj<T> make_obj(T t); 

template <typename T, typename RetVal> 
RetVal ret_obj(T t); 

template <typename T> 
class Obj { 
private: 
    T & t; 
    Obj (T & t) : t(t) { } 
    Obj() = delete; 

    friend Obj make_obj<T>(T t); 

    template <typename RetVal> 
     friend RetVal ret_obj<T, RetVal>(T t); 
}; 

template <typename T> 
Obj<T> make_obj(T t) { 
    return Obj<T>(t); 
} 

template <typename T, typename RetVal> 
RetVal ret_obj(T t) { 
    return RetVal(make_obj(t).t); 
} 

내가 같은 질문이 이미 this post에 요청 된 것으로 알고 있지만, 허용 대답은 내가 원하는 것을 할 수없는 것 : T2 차종에 매개 변수 이름을 변경하는 나는 이런 식으로 뭔가를 달성하고 싶습니다 함수는 모든 객체의 전문화의 친구이고, 나는 계속하고 싶습니다. T은 클래스와 같습니다.

+1

짐작할 수 있듯이 "나는 할 수 없다"라고 말하고 싶습니다. 도우미'struct'를 통해 함수를 수신 거부하는 것과 같이 작동하게하는 해결 방법이있을 것입니다. – Yakk

+1

불가능합니다. 프렌드 선언은 부분 전문화를 선언 할 수 없습니다. –

+0

@Yakk 그래, 내가 다른 수업을 쓸 수 있다고 생각 했어. 나는 이것을하기위한 직접적인 방법이 있는지 의아해했다. 그렇지 않으면 너무 나쁘다. : –

답변

2

friend 선언은 부분 특수화를 참조 할 수 없습니다. 특정 전문화 또는 기본 템플릿을 참조합니다. 또한 함수 템플릿은 부분적으로 특수화 될 수 없습니다. 기능 템플릿 수없는 무엇
하지만 클래스 템플릿을 사용하여 자주 행할 :

template <typename T> 
struct ret_obj_helper { 
    // Here goes the original definition of ret_obj - the important difference 
    // is the location of the template parameter T, which is the one 
    // fixed by the friend declaration below 
    template <typename RetVal> 
    RetVal ret_obj(T t) {return RetVal(make_obj(t).t);} 
}; 

// I guess RetVal, having to be explicitly specified, better goes first (?) 
template <typename RetVal, typename T> 
RetVal ret_obj(T&& t) 
{ 
    // Overcomplicated for the sake of perfect forwarding 
    return ret_obj_helper<typename std::remove_reference<T>::type>{}. 
     template ret_obj<RetVal>(std::forward<T>(t)); 
} 

template <typename T> 
class Obj { 
private: 
    T t; 
    Obj (T t) : t(t) { } 
    Obj() = delete; 

    friend Obj make_obj<T>(T t); 

    // Make all specializations of the member function template 
    // of ret_obj_helper<T> a friend, regardless of the return type 
    template <typename RetVal> 
    friend RetVal ret_obj_helper<T>::ret_obj(T t); 
}; 

Demo.

+0

그래, 위의 설명을 읽은 후에이 문제가 해결 될 것임을 알았습니다. 참조가 제거되지 않으면 함수를 호출하지 않으면 컴파일되지 않습니다. –

+0

공용 정적 멤버 대신 공용 구조체를 사용하면 어떤 이점이 있습니까? 캡슐화 정도에 차이가 없음을 알 수 있습니다. 공용 함수는 친구, 그것은 추한 공용 인터페이스를 통과해야합니다. – user877329

관련 문제