英文:
Is it possible to specialize a namespace depending on the template argument?
问题
这是我想要得到的内容。调用者无法访问B
命名空间。
template<typename T>
A::T foo1(std::vector<std::uint8_t> const& data)
{
return foo2<B::T>(data);
}
T
是在A
和B
中以不同方式定义的类型。我尝试解决这个问题,但似乎唯一可行的解决方案是像这样重载它:
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);
}
这是一个不错的解决方案,但每当需要处理新类型(比如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.
template<typename T>
A::T foo1(std::vector<std::uint8_t> const& data)
{
return foo2<B::T>(data);
}
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:
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);
}
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
,要么使用模板特化。
// 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<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);
}
如果B
中的类型与A
中的类型相同,那么你可以将这些类型导入到A
而不是定义相同的结构体。
// 导入整个命名空间
namespace A {
using namespace B;
}
// 或者只导入类型
namespace A {
using B::typeX;
using B::typeY;
....
}
// 然后直接使用这些类型
template<typename T>
T foo1(std::vector<std::uint8_t> const& data)
{
return foo2<T>(data);
}
英文:
The only way to do this AFAIK is to use some kind of type map, either by using std::conditional
or template specialization.
// 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; }
....
And then use the map in the functions
template<typename AType>
AType foo1(std::vector<std::uint8_t> const& data)
{
return foo2<b_type_t<AType>>(data);
}
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.
// 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);
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论