是否可以根据模板参数专门化命名空间?

huangapple go评论129阅读模式
英文:

Is it possible to specialize a namespace depending on the template argument?

问题

这是我想要得到的内容。调用者无法访问B命名空间。

  1. template<typename T>
  2. A::T foo1(std::vector<std::uint8_t> const& data)
  3. {
  4. return foo2<B::T>(data);
  5. }

T是在AB中以不同方式定义的类型。我尝试解决这个问题,但似乎唯一可行的解决方案是像这样重载它:

  1. void foo1(A::typeX& out, std::vector<std::uint8_t> const& data)
  2. {
  3. out = foo2<B::typeX>(data);
  4. }
  5. void foo1(A::typeY& out, std::vector<std::uint8_t> const& data)
  6. {
  7. out = foo2<B::typeY>(data);
  8. }

这是一个不错的解决方案,但每当需要处理新类型(比如typeZ)时,就需要添加一个新函数(请注意,将out参数传递为引用是重载的唯一方法,因为我不能使重载的函数直接返回它,因为它们唯一的区别是返回类型,这是不允许的)。再次强调,调用者只知道A命名空间,因此无法直接调用foo2()

我正在使用的C++标准是C++14(允许实验性命名空间)。

希望我表达足够清楚。谢谢!

我尝试映射输入/输出类型,但最终没有找到可行的解决方案,我和团队的其他成员也不喜欢那种方法。

我期望找到一种解决方法,使第一个代码片段工作(当然,不是我写的方式)。总的来说,我正在尝试专门化一个命名空间:如果输入参数类型是A::typeX,那么我使用B::typeX命名空间,否则如果输入参数类型是A::typeY,那么我使用B::typeY命名空间。

最好(请注意,最好)我希望找到一种不需要预定义映射的解决方案。

英文:

This is what I would like to get. The caller does not have access to B namespace.

  1. template&lt;typename T&gt;
  2. A::T foo1(std::vector&lt;std::uint8_t&gt; const&amp; data)
  3. {
  4. return foo2&lt;B::T&gt;(data);
  5. }

T is a type defined (in different ways) both in A and B. I tried to solve this problem but the only solution that seems feasible is to overload it like this:

  1. void foo1(A::typeX&amp; out, std::vector&lt;std::uint8_t&gt; const&amp; data)
  2. {
  3. out = foo2&lt;B::typeX&gt;(data);
  4. }
  5. void foo1(A::typeY&amp; out, std::vector&lt;std::uint8_t&gt; const&amp; data)
  6. {
  7. out = foo2&lt;B::typeY&gt;(data);
  8. }

It is a good solution but it requires a new function to be added every time a new type (say typeZ) needs to be handled (notice that passing the out parameter as a reference is the only way to overload it as I cannot make the overloaded functions return it directly since they would differ only for the returned type, and this is not permitted). Again, the caller only knows about A namespace, so it cannot call foo2() directly.

The standard of C++ I'm using is C++14 (experimental namespaces allowed)

I hope I,ve been clear enough. Thank you!

I tried to map the input/output type but I didn't end up with a working solution and neither me neither the rest of the team liked that.

I'm expecting to find a workaround to make the first code snippet working (of course, not exactly in the way I wrote it). In general, I'm trying to specialise a namespace: if the input parameter type is A::typeX then I use the B::typeX namespace, otherwise if the input parameter type is A::typeY then I use the B::typeY namespace.

Preferably (notice, preferably) I'd like a solution that doesn't require predefined mappings.

答案1

得分: 1

根据你的要求,以下是代码部分的中文翻译:

唯一的方法,据我所知,是使用某种类型映射,要么使用std::conditional,要么使用模板特化。

  1. // std::conditional
  2. template<class T>
  3. using b_type_t = typename std::conditional<
  4. std::is_same<T, A::typeX>::value, B::typeX,
  5. typename std::conditional<
  6. std::is_same<T, A::typeY>::value, B::typeY,
  7. ...>::type>::type;
  8. // 模板特化
  9. template<class T>
  10. struct b_type { };
  11. template<class T>
  12. using b_type_t = typename b_type<T>::type;
  13. template<> struct b_type<A::typeX> { using type = B::typeX; }
  14. template<> struct b_type<A::typeY> { using type = B::typeY; }
  15. ....

然后在函数中使用这个映射:

  1. template<typename AType>
  2. AType foo1(std::vector<std::uint8_t> const& data)
  3. {
  4. return foo2<b_type_t<AType>>(data);
  5. }

如果B中的类型与A中的类型相同,那么你可以将这些类型导入到A而不是定义相同的结构体。

  1. // 导入整个命名空间
  2. namespace A {
  3. using namespace B;
  4. }
  5. // 或者只导入类型
  6. namespace A {
  7. using B::typeX;
  8. using B::typeY;
  9. ....
  10. }
  11. // 然后直接使用这些类型
  12. template<typename T>
  13. T foo1(std::vector<std::uint8_t> const& data)
  14. {
  15. return foo2<T>(data);
  16. }
英文:

The only way to do this AFAIK is to use some kind of type map, either by using std::conditional or template specialization.

  1. // std::conditional
  2. template&lt;class T&gt;
  3. using b_type_t = typename std::conditional&lt;
  4. std::is_same&lt;T, A::typeX&gt;::value, B::typeX,
  5. typename std::conditional&lt;
  6. std::is_same&lt;T, A::typeY&gt;::value, B::typeY,
  7. ...&gt;::type&gt;::type;
  8. // template specialization
  9. template&lt;class T&gt;
  10. struct b_type { };
  11. template&lt;class T&gt;
  12. using b_type_t = typename b_type&lt;T&gt;::type;
  13. template&lt;&gt; struct b_type&lt;A::typeX&gt; { using type = B::typeX; }
  14. template&lt;&gt; struct b_type&lt;A::typeY&gt; { using type = B::typeY; }
  15. ....

And then use the map in the functions

  1. template&lt;typename AType&gt;
  2. AType foo1(std::vector&lt;std::uint8_t&gt; const&amp; data)
  3. {
  4. return foo2&lt;b_type_t&lt;AType&gt;&gt;(data);
  5. }

If the types in B are identical to the types in A then you can import the types into A instead of defining identical structs.

  1. // import the entire namespace
  2. namespace A {
  3. using namespace B;
  4. }
  5. // or import only the types
  6. namespace A {
  7. using B::typeX;
  8. using B::typeY;
  9. ....
  10. }
  11. // Then use the types directly
  12. template&lt;typename T&gt;
  13. T foo1(std::vector&lt;std::uint8_t&gt; const&amp; data)
  14. {
  15. return foo2&lt;T&gt;(data);
  16. }

huangapple
  • 本文由 发表于 2023年7月17日 21:56:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/76705179.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定