[英]Explicit Instantiation of Templated Overloaded Operator
以下代碼有效 :
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+
引入外部查找范圍,並且在cout
調用中使用了operator+
的情況下,采用默認模板值11,結果如預期的那樣:17(= 3 + 3 + 11)。
我的問題是如何更改using
子句以using
非默認模板值顯式實例化operator+
函數?
using Foo::operator+<42>
不起作用。
這是由於ISO C ++標准7.3.3.5所致: using聲明不應命名為template-id。
有沒有解決的辦法?
回答自己...
該問題似乎源於ISO C ++標准7.3.3.5:
使用聲明不應命名模板ID。
這會阻止接受: 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);
// }
// }
這個想法是用靜態方法Bar
將Foo
命名空間替換為結構模板。
這允許使用所需的參數實例化Foo
類型。
操作員只需通過外部定義和參數化的類型調用靜態方法。
ADL負責其余的工作。
在上面的示例中,用戶創建了2個新的命名空間Boo
和Goo
以具有plus運算符的2種不同的參數化。 最后,在使用時,用戶using directive
了所需版本的operator+
。
在這種方法中,似乎沒有指定默認參數值的選項。
在實際代碼中,運算符本身將存儲在代碼段文件中,以在聲明了參數化類型之后(示例中為Baz
)被#include
到代碼中。
這是一個更簡潔的版本,它使用簡單的模板化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;
}
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;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.