我想在我的库中有一个模板函数 func
这样用户就可以用自己的类型重载它。问题是我的类型系统是这样的
T := A<T>, B<T>, C
因此,template<class T> void func(A<T>);
需求template<class T> void func(B<T>);
如果它专门用于 T = B<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();
}
此示例无法编译。如果我们对 main.cpp
中的包含重新排序,它就会编译。作为
#include "C.hpp"
#include "B.hpp"
#include "A.hpp"
现在,这显然是一个 hack。使用此设计,用户将无法同时实例化 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
namespace 是我的库定义的 namespace 。
最佳答案
如果 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
}
关于c++ - 模板互递归,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46734122/