Загрузка символов пространства имен внутри функции для создания экземпляра шаблона

#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);