簡體   English   中英

模板化重載運算符的顯式實例化

[英]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);
//    }
// }

這個想法是用靜態方法BarFoo命名空間替換為結構模板。
這允許使用所需的參數實例化Foo類型。
操作員只需通過外部定義和參數化的類型調用靜態方法。
ADL負責其余的工作。

在上面的示例中,用戶創建了2個新的命名空間BooGoo以具有plus運算符的2種不同的參數化。 最后,在使用時,用戶using directive了所需版本的operator+

在這種方法中,似乎沒有指定默認參數值的選項。

在實際代碼中,運算符本身將存儲在代碼段文件中,以在聲明了參數化類型之后(示例中為Baz )被#include到代碼中。

拿2

這是一個更簡潔的版本,它使用簡單的模板化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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM