提问人:bitmap kid 提问时间:10/18/2023 最后编辑:Adrian Molebitmap kid 更新时间:10/18/2023 访问量:106
如何避免先验荒谬的重复模板专业化?
How to avoid a priori absurd duplicate template specialization?
问:
在下面的上下文中,有没有办法不使该方法专业化?请注意,它们几乎相同。这个例子故意很小。exec
就我而言,必须复制许多方法才能简单地更改演员表,这在使用模板时将是一个真正的悖论。也许做事的方式根本不是正确的?
#include <iostream>
using namespace std;
class D {
public:
D(uint8_t * mem) : m_mem(mem) {}
uint8_t *m_mem;
operator uint32_t*() { return reinterpret_cast<uint32_t*>(m_mem); }
};
template <typename T>
class C {
public:
C(T mem) : m_mem(mem) {}
T m_mem;
void exec();
};
template<>
void C<uint8_t*>::exec() {
cout << "exec = " << *reinterpret_cast<uint32_t*>(m_mem) << endl;
}
template<>
void C<D>::exec() {
cout << "exec = " << *static_cast<uint32_t*>(m_mem) << endl;
}
int main()
{
uint8_t mem[4] = {0,1,2,3};
C<uint8_t*> c1(mem);
C<D> c2(mem);
c1.exec();
c2.exec();
return EXIT_SUCCESS;
}
答:
2赞
Adrian Mole
10/18/2023
#1
在 C++20(及更高版本)中,可以在“constexpr if”语句中使用 convertible_to
概念,以选择要在单个函数模板中使用的强制转换类型。下面的代码替换了你的两个专业化exec
#include <concepts>
template<class T>
void C<T>::exec()
{
if constexpr (std::convertible_to<T, uint32_t*>) {
std::cout << "exec = " << *static_cast<uint32_t*>(m_mem) << std::endl;
}
else {
std::cout << "exec = " << *reinterpret_cast<uint32_t*>(m_mem) << std::endl;
}
}
在 C++20 之前(或者如果你想避免概念),有一个 std::is_convertible
类型特征,它将实现大致相同的目的:
#include <type_traits>
template<class T>
void C<T>::exec()
{
if constexpr (std::is_convertible<T, uint32_t*>::value) {
std::cout << "exec = " << *static_cast<uint32_t*>(m_mem) << std::endl;
}
else {
std::cout << "exec = " << *reinterpret_cast<uint32_t*>(m_mem) << std::endl;
}
}
评论
0赞
bitmap kid
10/19/2023
真的是一个很好的方法。如果有人想知道 if/else 的影响:在生成的二进制文件中没有它们的痕迹。
0赞
Adrian Mole
10/19/2023
@bitmapkid那是因为声明中的。constexpr
if
2赞
Igor Tandetnik
10/18/2023
#2
计算机科学中的大多数问题都可以通过添加间接级别来解决。也许有类似这样的东西:
uint32_t* AsUint32Ptr(uint8_t* mem) {
return reinterpret_cast<uint32_t*>(mem);
}
uint32_t* AsUint32Ptr(D& mem) {
return static_cast<uint32_t*>(mem);
}
有了它,你就不需要再专攻了:exec
template <typename T>
void C<T>::exec() {
cout << "exec = " << *AsUInt32Ptr(m_mem) << endl;
}
评论
0赞
bitmap kid
10/19/2023
很棒的解决方案,感谢间接的概念。
评论
AsUint32Ptr
exec
uint8_t
unsigned char
char
uint8_t
unsigned char