У меня есть класс с некоторыми необязательными параметрами шаблона:
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();
};
И следующий свободный интерфейс для их указания:
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(...))
).