簡體   English   中英

完美的位域轉發解決方法

[英]Perfect forwarding workaround for bit-fields

我正在尋找模板重載分辨率的位字段的解決方法。

我有一個函數,我模仿完美轉發其參數:

template <typename... Args> void f(Args &&...args) { }

如果我嘗試將其與位字段參數一起使用,如下所示:

struct bits { unsigned int foo:1; };
bits b{1};
f(b.foo);

......它無法編譯:

main.cpp:26:7: error: non-const reference cannot bind to bit-field 'foo'
    f(b.foo);
      ^~~~~

有沒有辦法重載f() ,使得它按值獲取位字段,但在常見情況下仍然通過引用獲取其他參數?

到目前為止,我還沒有。 例如,如果我添加一個按值獲取參數的重載...

main.cpp:27:5: error: call to 'f' is ambiguous
    f(b.foo);
    ^

它無法完成(至少不是你如何嘗試)因為標准如此(大膽強調我的):

13.3.3.1.4引用綁定[over.ics.ref]

4然而,綁定對特定參數的引用的其他限制不是基於引用的類型和參數,也不會影響標准轉換序列的形成。 [示例:具有“左值引用到int”參數的函數可以是可行的候選者,即使相應的參數是int位字段也是如此。 隱式轉換序列的形成將int比特字段視為整數值,並與參數完全匹配。 如果通過重載決策選擇該函數,則由於禁止將非常量左值引用綁定到位字段 (8.5.3) ,因此調用將是格式錯誤的。 - 結束例子]

這解釋了原因

  • 原始示例無法編譯,因為引用無法綁定到位字段
  • 添加一個重載template<typename... Arg> f(Args.. args)給你的含糊不清:過載資源以平局結束,並且引用綁定到位域禁止從未發揮作用。

http://coliru.stacked-crooked.com/view?id=b694c6cc3a52e0c14bedd6a26790d99d-e54ee7a04e4b807da0930236d4cc94dc

如果不好的話,可以做到。 我建議不要這樣做。 基本上,關鍵部分是因為你沒有指針或對位域的引用,所以你改為使用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;})

用法:

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;
}

我只是注意到我的bitfieldref_type假設值是一個bool ,而不是unsigned int ,但是我將把它固定為用戶的excersize。

這是我能想到的最佳答案:

template <typename... Args> void f(Args &&...args) { }

struct bits { unsigned int foo:1; };

template <typename T> const T constipate(T v)
{ return(static_cast<const T>(v)); }

void bar()
{
bits b{1};
f(constipate(b.foo));
}

編輯:有一個更簡單的解決方案,消除了對'constipate'模板的需求:

void bar()
{
bits b{1};
f(b.foo + 0);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM