2017-10-13 8 views
0

내 라이브러리에 템플릿 함수 func을 갖고 싶습니다. 사용자가 자신의 유형으로 오버로드 할 수 있습니다. 문제는 내 타입 시스템은 형태가 T = B<C>와 전문 경우 등, template<class T> void func(A<T>); 요구 template<class T> void func(B<T>);으로템플릿 상호 재귀

T := A<T>, B<T>, C

의 것입니다. 상호간에 func(B<T>)T = A<C>으로 인스턴스화하면 B<T> 전문화 과정은 A<T> 전문화 과정을 거쳐야합니다.

여기까지의 문제는 일부 공통 헤더에서 템플릿 기능을 선언하는 것으로 해결할 수 있습니다.

어떻게 접근해야할지 모르겠지만이 유형의 시스템을 확장 가능하게 만드는 방법입니다. 나는 사용자가 자신의 타입을 template<class T> class D<T>;으로 정의하고 자신의 template<class T> void func(D<T>);을 구현할 수 있기를 바란다. 이 경우 사용자가 그녀의 유형을 어떻게 선언 할 수 있는지 알 수 없으므로 전문 A<D<C>>에서 void func(A<T>);void func(D<T>);을 찾을 수 있습니다.

이렇게하는 표준 방법이 있습니까?

문제의

편집 최소한의 작업 예 :

// A.hpp

에서
namespace ns { 
template<class T> struct A { T t; }; 
template<class T> 
void fun (A<T> a) { fun(a.t); } 
} 

// B.hpp

namespace ns { 
template<class T> struct B { T t; }; 
template<class T> 
void fun (B<T> b) { fun(b.t); } 

// C.hpp

#include <iostream> 
namespace other { 
template<class T> 
struct C {}; 
} 

namespace ns { 
template<class T> 
void fun(other::C<T> c) { std::cout << "C" << std::endl; } 
} 

// main.cpp

#include "A.hpp" 
#include "B.hpp" 
#include "C.hpp" 

namespace ns { 
void f() { 
    fun(A<B<other::C<int>>>()); 
} 
} 


int main() { 
    ns::f(); 
} 

이 예는 컴파일되지 않습니다. 우리는이

#include "C.hpp" 
#include "B.hpp" 
#include "A.hpp" 

지금이 명확 해킹 main.cpp

로 포함 순서를 변경하면 그냥 컴파일합니다. 이 디자인을 사용하면 사용자는 A<B<C<int>>>B<A<C<int>>>을 모두 인스턴스화 할 수 없습니다. 이에 대한 해결책은 AB을 다른 템플릿에 전달하고 A.hppB.hpp에 모두 포함시키는 것입니다. 이제는 라이브러리 사용자가 자신의 유형을 정의 할 때 문제가 발생합니다. 라이브러리 사용자가 자신의 형식 인 template<class T> class D;을 정의하면 선언을 전달할 수 없으며 A<D<C<int>>>을 인스턴스화하려고하면 컴파일이 실패합니다.

이 예제에서 네임 스페이스 other은 내가 제어 할 수없는 네임 스페이스를 나타내며 C은 다른 라이브러리의 기존 클래스를 나타냅니다. 이것은 일부 boost 클래스 또는 이와 유사한 것으로 생각할 수 있습니다. ns 네임 스페이스는 내 라이브러리에서 정의한 것입니다.

+3

몇 가지 실제 코드를 제시해주십시오. –

+0

"양식"이 의미하는 바를 추측 할 수는 있지만 쉽게 틀릴 수 있습니다. 아이디어를 스케치하는 실제 코드는 그 모호함의 대부분을 제거합니다. 'T : = A '은 동일한 문장에서 두 가지 다른 것을 의미하는 재사용'T'를 남용하는 것입니다. 쉼표가 이상한 재발을 나타내거나'T '될 수있다. 계획을 보여주는 질문을 편집하여 실제 코드를 작성하십시오. (이 코드는 컴파일해야합니다.) – Yakk

+0

': ='나는 'T'라는 용어에 문법을 정의하려고했습니다. 코드 컴파일이 포함 순서에 따라 달라지는 간단한 예제에서이 동작을 복제하려고합니다. – Lezkus

답변

1

fun()이 템플릿 클래스의 정적 메소드 인 경우는 어떻게됩니까?

클래스를 부분적으로 특수화 할 수 있습니까?

내 말은

같은 // 000.h

#ifndef h_000__h 
#define h_000__h 

namespace ns 
{ 
    template <typename T> 
    struct foo; 
} 

#endif 

// 001.h

#ifndef h_001__h 
#define h_001__h 

#include <iostream> 

#include "000.h" 

namespace ns 
{ 
    template<class T> 
    struct A 
    { T t; }; 

    template <typename T> 
    struct foo<A<T>> 
    { 
     static void fun (A<T> a) 
     { std::cout << "A<T> fun" << std::endl; foo<T>::fun(a.t); } 
    }; 
} 

#endif 

// 002.h

#ifndef h_002__h 
#define h_002__h 

#include <iostream> 

#include "000.h" 

namespace ns 
{ 
    template <typename T> 
    struct B 
    { T t; }; 

    template <typename T> 
    struct foo<B<T>> 
    { 
     static void fun (B<T> a) 
     { std::cout << "B<T> fun" << std::endl; foo<T>::fun(a.t); } 
    }; 
} 

#endif 

// 003.h

,363,210
#ifndef h_003__h 
#define h_003__h 

#include <iostream> 

#include "000.h" 

namespace other 
{ 
    template <typename T> 
    struct C 
    { }; 
} 

namespace ns 
{ 
    template <typename T> 
    struct foo<other::C<T>> 
    { 
     static void fun (other::C<T> a) 
     { std::cout << "C<T> fun" << std::endl; } 
    }; 
} 

#endif 

// MAIN.CPP

#include "001.h" 
#include "002.h" 
#include "003.h" 

namespace ns 
{ 
    void f() 
    { 
     using type = A<B<other::C<int>>>; 

     foo<type>::fun(type{}); 
    } 
} 

int main() 
{ 
    ns::f(); // print A<T> fun \n B<T> fun \n C<T> fun \n 
} 
+0

정확히 내가 찾던 해결책입니다. 고맙습니다! – Lezkus