我有一些可选的模板参数类避免不必要的模板实例:在流畅的界面
struct option1_default_t {};
struct option2_default_t {};
template <typename T,
typename option1_t = option1_default_t,
typename option2_t = option2_default_t>
class foo
{
public:
foo(option1_t option1 = option1_t(), option2_t option2 = option2_t());
void run();
};
和指定他们以下fluent interface:
template <typename T, typename option1_t, typename option2_t>
struct foo_runner
{
option1_t option1_;
option2_t option2_;
template <typename new_option1_t>
foo_runner<T, new_option1_t, option2_t> option1(new_option1_t new_option1)
{
return foo_runner<T, new_option1_t, option2_t>{new_option1, option2_};
}
template <typename new_option2_t>
foo_runner<T, option1_t, new_option2_t> option2(new_option2_t new_option2)
{
return foo_runner<T, option1_t, new_option2_t>{option1_, new_option2};
}
void run()
{
foo<T, option1_t, option2_t> f(option1_, option2_);
f.run();
}
};
template <typename T>
foo_runner<T, option1_default_t, option2_default_t> make_foo()
{
return foo_runner<T, option1_default_t, option2_default_t>();
}
这里是如何流利的例子接口被使用:
struct my_option1_t { ... };
struct my_option2_t { ... };
int main()
{
make_foo<int>()
.option1(my_option1_t(...))
.option2(my_option2_t(...))
.run();
}
这当然是一个简化版本锡安;在我的真实代码中有很多选项,在这个类的典型用法中,只有其中的一部分被指定,因此流畅接口的理由。
这个流畅的界面的问题是它引起不必要的模板实例化。例如,上面的示例实例化了foo
三次:foo<int, option1_default_t, option2_default_t>
,foo<int, my_option1_t, option2_default_t>
,最后是foo<int, my_option1_t, my_option2_t>
,这是我想要的。
这是有问题的,因为foo
是一个很大的类,并且实例化它的编译时代很昂贵。
有没有一种方法我可以改变流畅的界面的实施不改变接口如何使用使foo
只实例化一次,最后的参数呢?
请注意,接口不变的要求 - 即我作为使用流畅接口的例子所提供的完全相同的代码,继续保持不变 - 这是关键。如果没有这个要求,我可以轻松地重写流畅的接口来仅实例化foo
一次(例如,我可以将接口更改为run_foo(make_foo<int>().option1(...).option2(...))
)。
您确定此模板实例化是瓶颈吗? – 2012-01-02 01:37:40
你甚至确定有3个'foo'实例化的实例吗?我不明白他们为什么会这样。我只看到'foo_runner :: run()'的实例化。 –
MSalters
2012-01-02 08:23:06