2011-02-03 7 views
7

템플릿 매개 변수가 허용되지 않기 때문에 템플릿 매개 변수를 친구와 공유 할 수 없습니다. 어떻게하면 같은 효과를 얻을 수 있을까요?템플릿 매개 변수 추가하기

내가 원하는 것은 기본적으로 소유하고있는 개체 외부에서 사용할 수없는 형식입니다. 왜 오히려 요점을 말하지만, 정말로 알고 있어야한다면, 나는 소유 자원을 공유하는 문제에 답하는 일련의 스마트 포인터를 공식화하려고합니다. 그 자체 소유자 선언하지 않는 한

template < typename T, typename Owner > 
struct accessible_member 
{ 
private: 
    accessible_member() : val(T()) {} 
    accessible_member(T const& t) : val(t) {} 

    operator T&() { return val; } 
    operator T const&() const { return val; } 

    member_ptr<T> operator &() { return member_ptr<T>(val); } 

    friend class Owner; 
}; 

는 따라서 클래스가 구성원으로이 객체를 보유 할 수 없으며, 충분히 바보 경우 노출 : 그래서 내가 무엇을 찾고 있어요 것은 일 경우, 그래서 같은 것입니다 그것은 그대로, 바보 같은 교실 밖에서 사용하는 것은 불가능합니다.

+2

나는 마지막 단락에서와 같이 braindead 코드를 막으려 고 노력하지 않는다. C++에서는 충분히 열심히 노력하면 누군가 코드를 위반할 수 있다는 것을 받아 들여야합니다. –

+1

@Fred - 'const'와 RAII를 포함한 코드 안전 조치를 도입하려는 모든 시도에 대해 동일한 어리석은 인수를 사용할 수 있습니다. 당신은 다른 철학 아래에서 일할 수도 있지만 지침에 따라 구조가 올바로 사용하기 쉽고 잘못 사용하기 어려워 야한다고 규정합니다. 구조물 자체의 요점은 다른 것에서 제공되지 않은 안전 조치를 도입하는 것입니다. 내 질문에 대한 귀하의 이의 제기가 중복되고, 제자리에서 벗어나고, 솔직히 공세감을 느낍니다. –

+2

@ NoahRoberts : 1) 이것은 올바르게 사용하기 쉽지 않습니다. 2) Const 및 RAII는 잘못 사용하기 쉽습니다. 3) 당신의 이해 부족 ("나는 그 점을 보지 못한다")을 어떻게 공격적이라고 생각할 수 있습니까? 나 자신을 보호하기 위해 내 대신에 화를 내고 있습니까? –

답변

3

당신은이를 사용할 수 있으며, 그런 다음 모든 소유자가 소유자에서 상속 받도록하십시오.

그런 다음 개인 accessible_member 에 사용되는 방법을 포장 소유자 클래스를 사용할 수 있습니다.
accessible_member소유자에게에 액세스 할 수 있습니다. Friend는 상속되지 않으므로 Owner를 상속 한 모든 클래스가 accessible_member을 사용할 수 있도록 필요한 메서드를 제공 (랩) 할 수 있습니다.

2 단계 솔루션이지만 캡슐화 수준을 유지합니다.

template < typename U > 
struct Owner 
{ 
    protected: 
    accessible_member<U> newAccessible_member() { return accessible_member<U>(); } 
    accessible_member<U> newAccessible_member(U const& u) { return accessible_member<U>(u); } 
    ..... 

}; 

template < typename T > 
struct accessible_member 
{ 
private: 
    accessible_member() : val(T()) {} 
    accessible_member(T const& t) : val(t) {} 

    operator T&() { return val; } 
    operator T const&() const { return val; } 

    member_ptr<T> operator &() { return member_ptr<T>(val); } 


    template < typename U> friend class Owner; 
}; 

그런 다음 당신은 보호 방법을 사용하여 소유자로부터 상속 구조체에 간접적으로 accessible_member를 사용할 수 있습니다

struct Blah: Owner<int> 
{ 
    void Dosomething() { 
     accessible_member<int> blah= newAccessible_member(); 
    } 
}; 

봐 마지막 예제에서 Template Friends에서.

+1

우정은 상속되지 않으므로 어떻게 작동하는지 알 수 없습니다. –

+0

그는 Owner를 래퍼로 사용하고 Owner에서 개인적으로 메서드를 래핑 할 수 있습니다. –

+0

이 대답의 목적이나 의견을 이해하지 못합니다. –

0

간단하게 accessible_member에서 상속받은 개인 중첩 유형을 정의하는 것은 어떻습니까? 그것을 생각하러 많이 사용 아마 그래서 여전히 원래 accessible_member 유형을 의미 물론

class Owner 
{ 
    template < typename T > 
    class accessible_member : public ::accessible_member<T> {}; 
}; 

같은 뭔가 누구나 사용할 수 있습니다.

+0

소유자를 Owner :: accessible_member의 친구로 만들고 privately inherited :: accessible_member를 만든 경우이 방법이 유용 할 수 있습니다. 하지만 Owner :: accessible_member에서 많은 보편적 인 포워딩이 필요합니다. –

5

당신은 C++ 98/03에 대해 정확합니다. 그러나 C++ 0X은 (n3225 11.4/3)이 구문을 사용하여이 작업을 수행 할 수 있습니다 : 당신의 컴파일러는 당신이 할 수있게된다 경우

friend Owner; 

을 참조하십시오. C++ 0x 지원을 사용하도록 설정하십시오. 그렇지 않으면 해결 방법이 이보다 있습니다

struct Owner 
{ 
    typedef Owner self; 
}; 

...

그런 다음 컴파일러에 따라 중 하나를

friend typename Owner::self; 

나 :

friend class Owner::self; 
+1

'typedef Owner Owner_typedef;가 잘못되었습니다. 친구 클래스 Owner_typedef;'?어쨌든, 구조체 매개 변수와 동일한 이름을 선택하는 것은 정말 나쁜 생각입니다. –

+0

'template'을 사용하여 템플릿 매개 변수에 'self'중첩 형식 요구 사항을 드롭 할 수 있습니까? struct identity {typedef T type; };'Owner :: self를 idonity :: type으로 변경하고 동일한 컴파일러에서 작업하도록 하시겠습니까? –

+0

@BenVoigt : 왜 그렇게 나쁜 생각입니까? 어쨌든 여기서는 예제로 사용됩니다. –

1

7.1.5.3 P2는 말한다 :

[참고 :이 의미, 그 템플릿 타입 매개 변수 T, 선언 친구 클래스 T와 클래스 템플릿 내에서; ]

결과적으로 어떤 의미에서든 사용자를 허용하는 솔루션은 표준을 준수하지 않을 수 있습니다. 내가 볼 수

+2

상황을 해결하는 표준 인용문은 정확히 답변이 아니지만 확실하게 다운 그레이드 할 자격이 없습니다. –

+2

질문을 언급하지 않으면 실제로 "대답"을 downvote하는 가장 큰 이유입니다. 특히 질문 자체에서 말하지 않은 내용을 말하지 않을 때는 "템플릿 매개 변수를 친구에게 허용 할 수 없기 때문에 표준에서 허용하지 않습니다." –

0

유일한 해결 방법은 오히려 추악하고 CRTP 사용

template <typename T> 
struct CanUseAccessibleMember 
{ 
    template <typename T> 
    static const T& get(const accessible_member<T>& m) 
    { return static_cast<const T&>(m); } 

    // Etc. You can even specialize this class. 
}; 

struct ExampleOwner 
    : protected CanUseAccessibleMember<ExampleOwner> 
{ 
    // Do whatever you want with accessible members here 
    // but you have to use the get syntax 
}; 

template <typename T, typename Owner> 
class accessible_member 
{ 
    // Implement members as you did 

    friend struct CanUseAccessibleMember<Owner>; 
}; 
+0

accessible_member의 ctors, 메서드 및 연산자는 개인적으로 (질문과 마찬가지로) ExampleOwner는 여전히 액세스 할 수 없습니다. –

+0

@Fred : 'CanUseAccessibleMember' 클래스에'get'과 같은 래퍼를 써야합니다. 회원 수가 적은 것 같으니 괜찮습니다. 그것이 내가 못생긴다고 말하는 이유입니다. –

0

까지 내가 볼 수있는 C++ 98에서, 약간의 변화와 함께 작동합니다.

: 그것은 그냥

struct Wrapper { typedef Owner type; }; 
friend class Wrapper :: type; 

friend Owner; 

을 변경 g++-4.1 -Wall -Wextra -pedantic -ansi -std=c++98

과 나를 위해 모든 경고없이 컴파일 (Template parameter as a friend I에 유래에서 그 대답을 얻었다,이 질문은 몇 번을왔다)

+0

하나의 연산자 ('operator const T &')를'public'으로 만들 때이 일반적인 아이디어가 유용하다는 것을 알았습니다.이렇게하면 '공개적으로 읽을 수 있지만 공개적으로 쓸 수없는'것으로 표시 할 수 있습니다. 즉 getter-and-setter의 말도 안되는 모든 것을 필요가 없습니다. –

관련 문제