私は自分のライブラリにテンプレート関数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>>>
の両方をインスタンス化することはできません。これに対する解決策は、A
とB
を別のテンプレートで宣言し、A.hpp
とB.hpp
の両方に含めることです。この問題は、ライブラリのユーザーが自分のタイプを定義できるようにしようとするときに発生します。ライブラリのユーザが自分自身のタイプをtemplate<class T> class D;
と定義した場合、宣言を転送することはできず、次にA<D<C<int>>>
をインスタンス化しようとすると、コンパイルは失敗します。
この例では、名前空間other
は、私が制御できない名前空間を表し、C
は、他のいくつかのライブラリの既存のクラスを表します。これは、いくつかのboost
クラスまたは同様のものと考えることができます。 ns
名前空間は、私のライブラリが定義した名前空間です。
いくつかの実際のコードを表示してください。 –
私はあなたが "フォーム"の意味を推測することができましたが、私は簡単に間違っている可能性があります。アイデアをスケッチしている実際のコードはあいまいさの多くを取り除きます。 'T:= A'は、少なくとも同じ文で2つの異なることを意味する再利用する 'T'の乱用であり、コンマがいくつかの奇妙な欺瞞を示しているのか、それとも' T 'できます。あなたの計画を示す質問を編集して実際のコードを書いてください。(このコードはコンパイルする必要があります) –
Yakk
':='私は 'T'という用語に文法を定義しようとしていました。 私は短い例でこの動作を再現しようとしています。コードコンパイルはインクルードの順序に依存します。 – Lezkus