我有一些可選的模板參數類避免不必要的模板實例:在流暢的界面
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