2017-10-13 9 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 'は、少なくとも同じ文で2つの異なることを意味する再利用する '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

#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

関連する問題