Я реализовал класс на основе политики. На данный момент шаблон класса и его классы политики объявлены в пространстве имен, называемом утилитой.
Проблема, с которой я сталкиваюсь, заключается в многословности результирующего кода. Код клиента выглядит так:
utility::MyTool<utility::AFirstPolicy, utility::ASecondPolicy>
my_function(utility::MyTool<utility::AnotherFirstPolicy, utility::AnotherSecondPolicy>);
Не очень читабельно, как видите. Я хотел бы получить что-то ближе от:
MyTool<AFirstPolicy, ASecondPolicy>
my_function(MyTool<AnotherFirstPolicy, AnotherSecondPolicy>);
Мне интересно, какова хорошая практика в таком случае. Вот что я могу придумать:
Наиболее очевидное решение. Не очень удобно для меня, потому что политики могут отличаться от функции к функции и приносить важную информацию об использовании функции. Я хотел бы, чтобы они появились непосредственно в прототипе функции. Кроме того, он вводит много имен типов в нескольких пространствах имен.
Положить using namespace utility;
или же using utility::MyTool; using utility::AFirstPolicy;
и т. д. в моем файле.
Инструмент часто используется в заголовочных файлах из других пространств имен, что делает директивы using не очень подходящими.
Мне не нравится этот подход, особенно потому, что у классов политики часто есть расплывчатые названия, которые имеют смысл только в их контексте.
Используйте что-то как
#define MY_TOOL(pcy1, pcy2) utility::MyTool<utility::##pcy1, utility::##pcy2>
преобразовать предыдущий код в
MY_TOOL(AFirstPolicy, ASecondPolicy)
my_function(MY_TOOL(AnotherFirstPolicy, AnotherSecondPolicy));
Я не уверен, что это более читабельно. Он работает только для фиксированного количества политик (это мой случай: всегда 2, без настроек по умолчанию) и не работает, если сами классы политик принимают параметры шаблона.
Какой из предыдущих подходов вы бы порекомендовали мне? Есть ли «лучшие практики»? Еще одна идея?
Если у тебя есть my_function(utility::MyTool<...>)
тогда я бы сказал, что my_function
принадлежит интерфейсу шаблона класса utility::MyTool<...>
, Другими словами, my_function
сам принадлежит к namespace utility
,
Это означает, что вы можете написать код в нужной сокращенной форме:
namespace utility {
typedef MyTool<AFirstPolicy, ASecondPolicy> SomeTool;
my_function(SomeTool);
}
Вы можете прочитать больше об интерфейсах и пространствах имен в этом старом столбце «Что в классе» Херб Саттер.
Обратите внимание, что даже если вы хотите использовать функции в других пространствах имен с классами из namespace utility
, вы все еще можете открыть это пространство имен и определить класс политики прямо здесь и сделать что-то вроде
// SomeHeader.hpp
namespace bla {
// your classes and functions
}
// reopen namespace utility
namespace utility {
typedef MyTool<AFirstPolicy, ASecondPolicy> SomeTool;
}
namespace bla {
typedef utility::SomeTool BlaTool; // or using-declaration
my_function(BlaTool);
}
Это, конечно, более многословно, чем определение my_function
внутри пространства имен утилиты, но, по крайней мере, вы можете собрать все различные политики, не слишком много печатая.
Других решений пока нет …