以下代码works:
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
子句以使用非 -default模板值显式实例化operator+
函数?
第using Foo::operator+<42>
行不起作用
这是由于ISO C ++标准7.3.3.5:使用声明不应命名模板ID。
有没有解决的办法?
答案 0 :(得分:2)
回答自己...... 问题似乎源于ISO C ++标准7.3.3.5:
使用声明不得命名模板ID。
这可以阻止接受:using Foo::operator+<42>
。
作为一种解决方法,我找到了以下解决方案,它以我需要的方式完成了额外的命名空间重定向。代码可能仍然需要一些按摩,但它确实完成了任务,用户方面的重复最少。
查看有效版本here。
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
,以获得plus运算符的2个不同参数化。最后,在使用时,用户会使用operator+
带来所需的using directive
版本。
在这种方法中,似乎没有指定默认参数值的选项。
在实际代码中,操作符本身将存储在一个片段文件中,在声明参数化类型(示例中为#include
)后Baz
编入代码。
Here's一个更简洁的版本,它使用一个简单的模板化traits类,并避免额外的命名空间和操作符重定向函数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;
}
答案 1 :(得分:1)
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;
}
}