s4y*_*s4y 5 c++ templates bit-fields perfect-forwarding c++11
我正在寻找模板重载解析中位域的解决方法。
我有一个函数模板,用于完美转发其参数:
template <typename... Args> void f(Args &&...args) { }
Run Code Online (Sandbox Code Playgroud)
如果我尝试将它与位域参数一起使用,如下所示:
struct bits { unsigned int foo:1; };
bits b{1};
f(b.foo);
Run Code Online (Sandbox Code Playgroud)
...它无法编译:
main.cpp:26:7: 错误:非常量引用无法绑定到位字段“foo”
f(b.foo);
^~~~~
有没有办法重载f(),使其按值获取位字段,但在常见情况下仍按引用获取其他参数?
到目前为止我还做不到。例如,如果我添加一个按值接受参数的重载......
main.cpp:27:5: 错误:对“f”的调用不明确
f(b.foo);
^
如果做得不好的话,也是可以做到的。我建议不要这样做。基本上,关键部分是因为您不能拥有对位字段的指针或引用,所以您可以使用 lambda来为您设置位字段。
我和下一个人一样不喜欢宏,但这是我能想到的避免要求调用者在调用站点放入 lambda 的唯一方法。
template<class assigner_type>
struct bitfieldref_type {
bitfieldref_type(bool value, assigner_type&& assign) :value(value), assign(std::move(assign)) {}
operator bool() const {return value;}
bitfieldref_type& operator=(bool v) {assign(v); value=v; return *this;}
private:
bool value;
assigner_type assign;
};
template<class assigner_type>
bitfieldref_type<assigner_type> make_bitfieldref(bool value, assigner_type&& assign)
{return {value, std::move(assign)};}
//macro is optional
#define bitfieldref(X) make_bitfieldref(X, [&](bool v)->void{X=v;})
Run Code Online (Sandbox Code Playgroud)
用法:
template <class T, typename... Args> void proof_it_works(T&& first)
{first = 0;}
template <class T, typename... Args> void proof_it_works(T&& first, Args &&...args) {
first = 0;
proof_it_works(std::forward<Args>(args)...);
}
template <typename... Args> void f(Args &&...args) {proof_it_works(std::forward<Args>(args)...);}
int main() {
struct bits { unsigned int foo:1; };
bits b{1};
int a = -1;
float c = 3.14;
f(a, bitfieldref(b.foo), c);
std::cout << a << b.foo << c;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我刚刚注意到我bitfieldref_type假设该值是 a bool,而不是 a unsigned int,但我将修复它作为用户的练习。