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

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

提问人:senior_questions_asker 提问时间:7/17/2023 最后编辑:senior_questions_asker 更新时间:7/17/2023 访问量:60

问:

这就是我想得到的。调用方无权访问命名空间。B

template<typename T>
A::T foo1(std::vector<std::uint8_t> const& data)
{
  return foo2<B::T>(data);
}

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

    void foo1(A::typeX& out, std::vector<std::uint8_t> const& data)
    {
      out = foo2<B::typeX>(data);
    }

    void foo1(A::typeY& out, std::vector<std::uint8_t> const& data)
    {
      out = foo2<B::typeY>(data);
    }

这是一个很好的解决方案,但它需要每次需要处理新类型(比如)时添加一个新函数(请注意,将 out 参数作为引用传递是重载它的唯一方法,因为我无法让重载函数直接返回它,因为它们只会对返回的类型有所不同, 这是不允许的)。同样,调用方只知道命名空间,因此它不能直接调用。typeZAfoo2()

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

我希望我已经足够清楚了。谢谢!

我试图映射输入/输出类型,但我最终没有得到一个有效的解决方案,我和团队的其他成员都不喜欢这样。

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

最好(注意,最好)我想要一个不需要预定义映射的解决方案。

C++ Templates 命名空间 C++14 专项课程

评论

0赞 463035818_is_not_an_ai 7/17/2023
void foo1(B::typeY& out, ....这是错别字吗?从我期望的其余部分的描述中void foo1(A::typeY& out, ...
0赞 463035818_is_not_an_ai 7/17/2023
foo2返回一个 ?A::T
0赞 senior_questions_asker 7/17/2023
你是对的。我编辑了。

答:

1赞 Mestkon 7/17/2023 #1

执行此 AFAIK 的唯一方法是使用某种类型映射,通过使用或模板专用化。std::conditional

// std::conditional
template<class T>
using b_type_t = typename std::conditional<
    std::is_same<T, A::typeX>::value, B::typeX,
    typename std::conditional<
        std::is_same<T, A::typeY>::value, B::typeY, 
        ...>::type>::type;

// template specialization
template<class T>
struct b_type { };
template<class T>
using b_type_t = typename b_type<T>::type;

template<> struct b_type<A::typeX> { using type = B::typeX; }
template<> struct b_type<A::typeY> { using type = B::typeY; }
....

然后在函数中使用地图

template<typename AType>
AType foo1(std::vector<std::uint8_t> const& data)
{
    return foo2<b_type_t<AType>>(data);
}

如果 中的类型与 中的类型相同,则可以将类型导入到而不是定义相同的结构中。BAA

// import the entire namespace
namespace A {
using namespace B;
}

// or import only the types
namespace A {
using B::typeX;
using B::typeY;
....
}

// Then use the types directly
template<typename T>
T foo1(std::vector<std::uint8_t> const& data)
{
    return foo2<T>(data);
}