有模板方法但不公开实现
Have a template method but not expose implementation
我在TFRuntime.h
中有一个函数
class TFRuntime {
...
template <typename T>
Status computeXYSlice(Volume<T>* input, int zCoord, Volume<T> *output);
...
}
TFRuntime.cpp包括tensorflow库header如
#include <tensorflow/cc/ops/standard_ops.h>
#include <tensorflow/cc/saved_model/loader.h>
我不想将这些包含在 header 中,因为这会迫使任何使用 TFRuntime 的人也包含它们。但是,如果我希望 computeXYSlice
函数允许任何类型,我必须在 .h 文件中包含实现。然而,实现需要上述 tensorflow headers。
如何解决这个问题?我可以明确地 'instantiate' 只有 computeXYSlice
函数的某些变体吗?例如,T
是 float
或 int
或 double
?或者有更好的方法吗?
Could I explicitly 'instantiate' only certain variants of the computeXYSlice function? E.g., where T is float or int or double?
你可以,它们的实现不需要在 header 中。稍后我会谈到这一点。但是如果你真的想允许任何类型那么你的模板必须是header。就是这样。
如果您希望只支持一小组类型,作为模板实例化,而不重载(有时在查找时可能会有所不同),标准有一个机制 显式模板实例化.
您的 header 看起来像这样...
class TFRuntime {
public:
template <typename T>
Status computeXYSlice(Volume<T>* input, int zCoord, Volume<T> *output);
};
...您的实现文件将包含显式实例 定义,就像这样...
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>*);
您必须包含显式实例化定义,否则您的程序是 ill-formed,不需要诊断。 The template function must be defined when implicit instantiation occurs, unless an explicit instantiation appears somewhere.
这有点麻烦。但是如果你的最终目标确实是有一堆实例化(而不是重载),那么你就是这样把它们联系在一起的。
我个人会继续使用 public 模板,当然,您将被迫将随附的 headers 与您自己的模板一起交付,但我会咬紧牙关在这种情况下,为 class.
的用户留下最大可能的灵活性
您至少可以将其隐藏在一个单独的“.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);
};
因为现在模板函数是私有的,不能从 "outside" 调用它,您可以在 .cpp 文件中安全地实现它(其中只实例化所需的特化),连同正常调用模板函数的重载函数(您需要显式提供模板参数以防止递归——或者为模板函数指定一个不同的名称)。 不要实现已经在class定义中的重载,否则它们会被内联并且您再次将模板函数暴露给其他classes,要求实现可用再次...
您可以将使用过的(非模板化的)Tensorflow 功能包装在您自己的 header/sources 文件中,并从您的模板化代码中调用您的包装器:
// 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 发生更改,可能会停止工作。
我在TFRuntime.h
中有一个函数class TFRuntime {
...
template <typename T>
Status computeXYSlice(Volume<T>* input, int zCoord, Volume<T> *output);
...
}
TFRuntime.cpp包括tensorflow库header如
#include <tensorflow/cc/ops/standard_ops.h>
#include <tensorflow/cc/saved_model/loader.h>
我不想将这些包含在 header 中,因为这会迫使任何使用 TFRuntime 的人也包含它们。但是,如果我希望 computeXYSlice
函数允许任何类型,我必须在 .h 文件中包含实现。然而,实现需要上述 tensorflow headers。
如何解决这个问题?我可以明确地 'instantiate' 只有 computeXYSlice
函数的某些变体吗?例如,T
是 float
或 int
或 double
?或者有更好的方法吗?
Could I explicitly 'instantiate' only certain variants of the computeXYSlice function? E.g., where T is float or int or double?
你可以,它们的实现不需要在 header 中。稍后我会谈到这一点。但是如果你真的想允许任何类型那么你的模板必须是header。就是这样。
如果您希望只支持一小组类型,作为模板实例化,而不重载(有时在查找时可能会有所不同),标准有一个机制 显式模板实例化.
您的 header 看起来像这样...
class TFRuntime {
public:
template <typename T>
Status computeXYSlice(Volume<T>* input, int zCoord, Volume<T> *output);
};
...您的实现文件将包含显式实例 定义,就像这样...
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>*);
您必须包含显式实例化定义,否则您的程序是 ill-formed,不需要诊断。 The template function must be defined when implicit instantiation occurs, unless an explicit instantiation appears somewhere.
这有点麻烦。但是如果你的最终目标确实是有一堆实例化(而不是重载),那么你就是这样把它们联系在一起的。
我个人会继续使用 public 模板,当然,您将被迫将随附的 headers 与您自己的模板一起交付,但我会咬紧牙关在这种情况下,为 class.
的用户留下最大可能的灵活性您至少可以将其隐藏在一个单独的“.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);
};
因为现在模板函数是私有的,不能从 "outside" 调用它,您可以在 .cpp 文件中安全地实现它(其中只实例化所需的特化),连同正常调用模板函数的重载函数(您需要显式提供模板参数以防止递归——或者为模板函数指定一个不同的名称)。 不要实现已经在class定义中的重载,否则它们会被内联并且您再次将模板函数暴露给其他classes,要求实现可用再次...
您可以将使用过的(非模板化的)Tensorflow 功能包装在您自己的 header/sources 文件中,并从您的模板化代码中调用您的包装器:
// 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 发生更改,可能会停止工作。