Явная реализация шаблонного перегруженного оператора

Следующий код работает:

struct A
{
int v = 3;
};

namespace Foo
{
template <int k=11>
int operator+(A const& lhs, A const& rhs)
{
return lhs.v + rhs.v + k;
}
}

using Foo::operator+;

int main()
{
A a1, a2;
std::cout << a1 + a2 << std::endl;
return 0;
}

using Foo::operator+; директива приносит Foo::operator+ во внешнюю область поиска и когда operator+ используется в cout вызовите, значение шаблона по умолчанию 11 принимается и результат, как и ожидалось: 17 (= 3 + 3 + 11).

Мой вопрос, как изменить using пункт, чтобы явно создать экземпляр operator+ функция с не-значение шаблона по умолчанию?

Линия using Foo::operator+<42> не работает.
Это связано со стандартом ISO C ++ 7.3.3.5: Объявление использования не должно называть идентификатор шаблона.
Это можно обойти?

0

Решение

Отвечаю сам …
Кажется, что проблема связана с ISO C ++ Standard 7.3.3.5:

Объявление использования не должно называть идентификатор шаблона.

Это предотвращает принятие: using Foo::operator+<42>,

В качестве обходного пути я нашел следующее решение, которое делает то, что мне нужно, за счет дополнительного перенаправления пространства имен. Код все еще может нуждаться в некотором массаже, но он выполняет задачу с минимальным дублированием на стороне пользователя.

Посмотреть рабочую версию Вот.

struct A
{
int v = 0;
};

template <int k>
struct Bar
{
static int plus(A const& lhs, A const& rhs)
{
return rhs.v + lhs.v + k;
}
};

namespace Boo
{
using Baz = Bar<42>; // same as `typedef Bar<42> Baz;`

//#include "foo_operators.h"namespace Foo
{
int operator+(A const& rhs, A const& lhs)
{
return Baz::plus(lhs, rhs);
}
}
}

namespace Goo
{
using Baz = Bar<3>;

//#include "foo_operators.h"namespace Foo
{
int operator+(A const& rhs, A const& lhs)
{
return Baz::plus(lhs, rhs);
}
}
}using namespace std;
int main()
{
{
using Boo::Foo::operator+;
A a1, a2;
cout << a1 + a2 << endl;
}

{
using Goo::Foo::operator+;
A a1, a2;
cout << a1 + a2 << endl;
}

return EXIT_SUCCESS;
}

// In real code extract to foo_operators.h: the partial file snippets to get #included multiple times
// namespace Foo
// {
//    int operator+(A const& rhs, A const& lhs)
//    {
//       return Baz::plus(lhs, rhs);
//    }
// }

Идея состоит в том, чтобы заменить Foo пространство имен с шаблоном структуры со статическими методами Bar,
Это позволяет создавать экземпляры Foo введите с помощью желаемых параметров.
Операторы просто вызывают статические методы через определенный и параметризованный тип.
ADL позаботится обо всем остальном.

В приведенном выше примере пользователь создал 2 новых пространства имен, Boo а также Goo иметь 2 разных параметризации оператора плюс. Наконец, в момент использования пользователь вводит желаемую версию operator+ с using directive,

В этом подходе нет возможности указать значения параметров по умолчанию.

В реальном коде сами операторы будут храниться в файле сниппета для #includeв код после объявления параметризованного типа (Baz в примере).

Взять 2

Вот гораздо более чистая версия, которая использует простой класс шаблонных признаков и избегает как дополнительного пространства имен, так и функции перенаправления оператора plus,

template <int k>
struct op_traits_t
{
static const int K = k;
};namespace Boo
{
using op_traits = op_traits_t<42>; // same as `typedef op_traits_t<42> op_traits;`
//#include "foo_operators.h"// this is a partial file snippet
int operator+(A const& rhs, A const& lhs)
{
return rhs.v + lhs.v + op_traits::K;
}
}

namespace Goo
{
using op_traits = op_traits_t<3>;
//#include "foo_operators.h"// this is a partial file snippet
int operator+(A const& rhs, A const& lhs)
{
return rhs.v + lhs.v + op_traits::K;
}
}

int main()
{
{
using Boo::operator+;
A a1, a2;
cout << a1 + a2 << endl;
}

{
using namespace Goo;
A a1, a2;
cout << a1 + a2 << endl;
}

return EXIT_SUCCESS;
}
2

Другие решения

std::cout << operator+<12>(a1, a2) << std::endl;

Но не делай этого. Оператор + должен вести себя неудивительно.

Используйте именованную функцию:

namespace Foo
{
template <int k=11>
int add_plus_k(A const& lhs, A const& rhs)
{
return lhs.v + rhs.v + k;
}
}
1

По вопросам рекламы [email protected]