c++可变模板删除函数逻辑
C++ Variadic Template Remove Function Logic
我已经能够进一步与我的可变模板从我之前的问题。我现在有一个新问题。在这个代码示例中:
#include <iostream>
#include <cstddef>
constexpr std::uint32_t Flag0 = 0x0001;
constexpr std::uint32_t Flag1 = 0x0002;
constexpr std::uint32_t Flag2 = 0x0004;
constexpr std::uint32_t FlagAll = 0xFFFF;
template<std::uint32_t...Cs>
struct flags_tag {constexpr flags_tag(){}; };
template<std::uint32_t...Cs>
struct make_flags{ using type=flags_tag<Cs...>; };
template<std::uint32_t...Cs>
using make_flags_t=typename make_flags<Cs...>::type;
template<std::uint32_t value>
class pValue_t
{
template<std::uint32_t StateMask, class flags>
friend class Compound;
};
template<> class pValue_t<Flag0>
{
public:
pValue_t() :
m_pValue0(reinterpret_cast<void*>(0xFFFFFFFF))
{}
protected:
void* m_pValue0;
};
template<> class pValue_t<Flag1>
{
public:
pValue_t() :
m_pValue1(reinterpret_cast<void*>(0xDEADBEEF))
{}
protected:
void* m_pValue1;
};
template<> class pValue_t<Flag2>
{
public:
pValue_t() :
m_pValue2(reinterpret_cast<void*>(0xCAFEBABE))
{}
protected:
void* m_pValue2;
};
template<std::uint32_t StateMask, class flags>
class Compound;
template<std::uint32_t StateMask, std::uint32_t...Cs>
class Compound< StateMask, flags_tag<Cs...> >:
public pValue_t<Cs>...
{
public:
void print()
{
if (IsStateValid(Flag0))
{
std::cout << this->m_pValue0 << 'n';
}
if ((StateMask & Flag1) == Flag1)
{
std::cout << this->m_pValue1 << 'n';
}
// *** THIS IS THE PROBLEM STATEMENT ***
if (IsStateValid(Flag2))
{
std::cout << this->m_pValue2 << 'n';
}
}
static bool IsStateValid(std::uint32_t stateMask)
{ return ((StateMask & stateMask) == stateMask); }
uint32_t m_stateMask;
};
using my_type = Compound< Flag0 | Flag1, make_flags_t<Flag0, Flag1>>;
int main() {
my_type test;
test.print();
}
print
函数包含对m_pValue2
的引用,当StateMask
包含Flag2
时,该引用有效。
现在,编译器警告它找不到m_pValue2
。我希望编译器删除引用m_pValue2
的代码块,当StateMask
(在编译时已知)不包含Flag2
(当IsStateValid()
为false)。
准确的错误如下:
main.cpp: In instantiation of 'void Compound<StateMask, flags_tag<Cs ...> >::print() [with unsigned int StateMask = 3u; unsigned int ...Cs = {1u, 2u}]':
main.cpp:95:18: required from here
main.cpp:80:27: error: 'class Compound<3u, flags_tag<1u, 2u> >' has no member named 'm_pValue2'
std::cout << this->m_pValue2 << 'n';
我希望这是可能的。在其他模板编程中,我使用IsStateValid()
编译出与StateMask
不匹配的代码段。但是,我从来没有试图编译掉可能丢失的成员变量。
有人有什么想法吗?
为什么它不工作
无论类型如何,函数模板中的所有分支都将被编译。IsStateValid(Flag2)
在编译时是否为false
并不重要,if
的主体必须是有效的代码。因为在这种情况下没有this->m_pValue2
,所以这是一个硬错误。
你能做些什么来修复它
你需要将每个打印标志函数转发给一个函数模板,该函数模板要么打印该值(如果存在),要么什么都不做(如果不存在)。我们可以在这里使用函数重载来提供帮助,并确保如果没有这样的标志,整个函数将不会被实例化。例如:
void print()
{
printImpl<Flag0>();
printImpl<Flag1>();
printImpl<Flag2>();
}
template <uint32_t F>
void printImpl() {
printImpl<F>(std::is_base_of<pValue_t<F>, Compound>{});
}
template <uint32_t F>
void printImpl(std::true_type ) {
// we DO have this flag
pValue_t<F>::print();
}
template <uint32_t F>
void printImpl(std::false_type ) {
// we do NOT have this flag
// so do nothing
}
此时您需要做的就是添加适当的print()
s。例如:
template<> class pValue_t<Flag2>
{
public:
pValue_t() :
m_pValue2(reinterpret_cast<void*>(0xCAFEBABE))
{}
void print() {
std::cout << m_pValue2 << 'n';
}
protected:
void* m_pValue2;
};
我让这个工作(工作示例),但它似乎很hackky。这表明这是可能的——希望一个比我更有经验的人能把它清理干净。
我们的想法是使IsStataValid
成为constexpr
,并将有问题的代码分离到另一个函数中,该函数有两个变体。被实例化的变量取决于编译时标志:
static constexpr bool IsStateValid(std::uint32_t stateMask)
{ return ((StateMask & stateMask) == stateMask); }
template <typename A = void,
typename T = typename std::enable_if<IsStateValid(Flag2), A>::type>
void blub(int x=0) {
std::cout << this->m_pValue2 << 'n';
}
template <typename A = void,
typename T = typename std::enable_if<!IsStateValid(Flag2), A>::type>
void blub(long x=0) {
}
然后在print()
中调用辅助函数而不是if
语句:
blub();
typename A
是一个虚拟参数,使enable_if
依赖于模板参数,以便SFINAE可以启动。blub
接受不同类型的第一个形参,因此编译器不会抱怨它不能被重载。
- 如何通过 getter 函数删除矢量的元素?
- C++类析构函数删除成员(如果"owner"?
- 使用私有析构函数删除动态分配的对象
- C ++(为什么)确实移动构造函数删除运算符=
- 析构函数删除错误的元素
- C++ 类析构函数删除部分但不是全部成员数据
- 如何使用 deleteEntry 函数 c++ 删除数组中的单个字符串
- 仅仅以避免隐式复制构造函数删除,使用shared_ptr而不是unique_ptr作为类成员明智
- 析构函数删除在 main 中声明的动态数组
- 如果未分配申报表,是否需要删除或处理动态数组?还是它被函数删除
- C++ 函数删除一行
- g++空函数删除是否递归工作
- C++析构函数删除东西(对象,指针?)太快
- C++析构函数删除包含动态数组作为数据成员的对象时的用法
- C++11 析构函数 = 删除
- 父类析构函数删除具有外部启动元素的子类
- 函数删除太多
- C++析构函数删除共享内存
- C++,如何让此函数删除存储在数组中的字符串
- 析构函数删除数组时出错