#c #templates #boost #namespaces #boost-range
#c #шаблоны #повышение #пространства имен #увеличение диапазона
Вопрос:
Я написал шаблонную operator =
функцию и присвоил ей уникальное пространство имен (я хочу использовать его только иногда, и это позволяет мне неявно).
Затем я хотел бы использовать эту функцию внутри другой шаблонной функции, которая использует operator =
свои операнды, но я не хочу оставлять ее висеть в таблице символов, ожидая ответа на каждый =
вызов, который я выполняю в любом месте моей программы. Я также должен сделать это внутри заголовка, который широко используется.
Основным примером этого является:
#define BOOST_RESULT_OF_USE_DECLTYPE
#include "boostrange.hpp"
#include "boostrangealgorithm.hpp"
#include <vector>
using std::vector;
namespace range_ops
{
template <class ForwardRange1, class SinglePassRange2>
inline ForwardRange1amp; operator =(ForwardRange1amp; left, const SinglePassRange2amp; right)
{
auto left_it = boost::begin(left);
auto right_it = boost::begin(right);
for (; left_it != boost::end(left); left_it, right_it)
*left_it = *right_it;
return left;
}
}
template <class SinglePassRange, class Value>
inline Value accumulate_increment(SinglePassRangeamp; rng, Value val)
{
typedef typename boost::range_value<SinglePassRange>::type range_val;
boost::for_each(rng, [amp;](const range_valamp; x) { val = x; });
return val;
}
template <class SinglePassRange>
inline typename boost::range_value<SinglePassRange>::type accumulate_increment(SinglePassRangeamp; rng)
{
return accumulate_increment(rng, typename boost::range_value<SinglePassRange>::type());
}
//using range_ops::operator =; // this works, but pollutes the global namespace with a templacised operator = function - yuck!
int main()
{
auto i = accumulate_increment(vector<int>(1)); // works fine
using range_ops::operator =; // want this here, but accumulate_increment can't see the operator = function
auto j = accumulate_increment(vector<vector<int>>(1));
}
Есть ли какой-либо способ достичь этого результата?
Ответ №1:
Существует только 1 функция увеличения, так как же вы ожидали, что предложение using в вызывающем объекте повлияет на саму функцию увеличения — как она должна находить operatior ?
Комментарии:
1. Поскольку функции шаблона создаются только на сайте вызова, поэтому вам нужно, чтобы функция была видна только в момент ее первого вызова. Проблема в том, что функции шаблона создаются в начале функции, которая их вызывает, а не в фактической строке, где они впервые используются. Следовательно, использование объявлений внутри самой функции не рассматривается при создании экземпляра функции шаблона.
2. Айджей — вы должны опубликовать это как ответ, а не мой слабый ответ
3. Хах, это не ответ, это описание того, почему это сложно. Я пытаюсь спросить, есть ли способ обойти это!
4. Я не понимаю, что вы пытаетесь сделать — operator принимает 2 класса. Можете ли вы привести лучший пример из реального мира, чтобы, возможно, увидеть, что вы действительно пытаетесь сделать
5. В принципе, я написал шаблонную функцию, которая позволяет увеличивать диапазон. например.
vector<int> x, y; x = y;
Это полностью универсальная функция, которая может использовать все, что соответствуетrange
концепции Boost. Из-за того, насколько это универсально, мне не нравится, когда оно висит в таблице символов, поэтому я поместил его вrange_ops
пространство имен. Я также написал пользовательскуюaccumulate
подобную функцию, которая работает в автономном режимеoperator =
, просто потому, что я почти всегда так ее использую. Сейчас я пытаюсь использовать их в комбинации.
Ответ №2:
Даже если бы вы могли это сделать, я бы не рекомендовал. Кто-то, использующий ваш код, должен ожидать, что внутреннее поведение объекта не будет зависеть от некоторого внешнего состояния (вашей настройки пространства имен), которое явно не передается в него и не перемещается с ним (не то, что зависит от того, где оно географически находится в исходном файле).
Перегрузка оператора уже является особенностью, которая граничит с запутыванием, за исключением случаев, когда операнды являются вещами, которые обычно не поддерживают этот оператор в природе.
Если вы хотите реализовать что-то подобное, вам следует сделать это, установив состояние объекта, которое изменяет поведение оператора, который вы перегружаете, например, члена SetOtherOperatorOverload(TRUE);