我在TFRuntime.h中有一个函数
class TFRuntime {
...
template <typename T>
Status computeXYSlice(Volume<T>* input, int zCoord, Volume<T> *output);
...
}
TFRuntime.cpp包含诸如tensorflow库头
#include <tensorflow/cc/ops/standard_ops.h>
#include <tensorflow/cc/saved_model/loader.h>
我不想在标头中包含这些内容,因为这将迫使使用TFRuntime的任何人也将它们包含在内。但是,如果我希望computeXYSlice
函数允许任何类型,则必须在.h文件中包括实现。但是该实现需要上面提到的张量流头。
如何解决这个问题?我是否可以仅“实例化” computeXYSlice
函数的某些变体?例如,T
是float
还是int
或double
?还是有更好的方法?
答案 0 :(得分:5)
我可以只显式地“实例化” computeXYSlice函数的某些变体吗?例如,其中T为float或int或double?
您可以,并且它们的实现不必在标头中。一会儿,我会解决的。但是,如果您确实要允许任何类型,则您的模板必须位于标头中。就是这样。
如果您只希望支持一小部分类型(如模板实例化)而又不过载(有时在查找时可能有所作为),则该标准具有显式模板实例化的机制。< / p>
您的标题看起来像这样...
class TFRuntime {
public:
template <typename T>
Status computeXYSlice(Volume<T>* input, int zCoord, Volume<T> *output);
};
...并且您的实现文件将包含显式实例化 definitions ,就像这样...
template <typename T>
Status TFRuntime::computeXYSlice(Volume<T>* input, int zCoord, Volume<T> *output) {
// Implement it
}
template
Status TFRuntime::computeXYSlice(Volume<int>*, int, Volume<int>*);
template
Status TFRuntime::computeXYSlice(Volume<double>*, int, Volume<double>*);
您必须包括显式的实例化定义,否则您的程序格式错误,不需要诊断。 The template function must be defined when implicit instantiation occurs, unless an explicit instantiation appears somewhere。
这有点麻烦。但是,如果您的最终目标是确实有很多实例化(而不是重载),那么这就是将它们捆绑在一起的方式。
答案 1 :(得分:3)
您可以将使用过的(非模板的)Tensorflow功能包装在您自己的标头/源文件中,并从模板代码中调用包装器:
// wrapper.h:
void some_function();
// wrapper.cpp:
#include <tensorflow/...>
void some_function() { /* use tensorflow stuff here */ }
// TFRuntime.h:
#include "wrapper.h" // no inclusion of Tensorflow headers involved
template <typename T>
void some_templated_function() {
some_function();
}
实时演示:https://wandbox.org/permlink/dWRT0AEi8alylTQB
但是,此解决方案增加了代码冗余,并且如果Tensorflow API发生更改,可能会停止工作。
答案 2 :(得分:2)
我个人将只使用公共模板,当然,您将被迫随后将随附的标头与您自己的标头一起提供,但在这种情况下,我只是简单地说一下,以为用户提供最大的灵活性班上的。
您至少可以将其隐藏在单独的“ .inl”或“ .impl”文件中(按您的意思不能解决,但使其不那么可见):
class TFRuntime
{
template <typename T>
Status computeXYSlice(Volume<T>* input, int zCoord, Volume<T>* output);
};
#include "TFRuntime.inl"
和:
#include <tensorflow/cc/ops/standard_ops.h>
#include <tensorflow/cc/saved_model/loader.h>
template <typename T>
Status TFRuntime::computeXYSlice(Volume<T>* input, int zCoord, Volume<T>* output)
{
// ...
}
如果您真的想限制可用数据类型的范围,可以通过重载来实现:
class TFRuntime
{
public:
Status computeXYSlice(Volume<int>* input, int zCoord, Volume<int>* output);
Status computeXYSlice(Volume<double>* input, int zCoord, Volume<double>* output);
Status computeXYSlice(Volume<unsigned long>* input, int zCoord, Volume<unsigned long>* output);
private:
template <typename T>
Status computeXYSlice(Volume<T>* input, int zCoord, Volume<T>* output);
};
由于现在模板函数是私有的,因此不能从“外部”调用它,您可以在.cpp文件中安全地实现它(仅实例化所需的特殊化),而普通的重载函数则可以调用模板函数(您需要显式提供template参数以防止递归–或为模板函数指定其他名称)。 不要在类定义中实现已经实现的重载,否则它们将被内联,并且您将模板函数再次公开给其他类,要求实现再次可用...