none
ラムダ式の場合の定義変換について RRS feed

  • 質問

  • いつもお世話になっております。

    VS2015U3 / Windows Kits(10.0.14393.0)で作業しています。

    -- A.h ---
    strcut Elm {
        int hclr;
        long hstl;
    };
    
    --- proc.h ---
    #include "A.h"
    
    CData data{
        int m_Color;
        long m_Style;
    }
    
    --- proc.cpp ---
    #include "proc.h"
    
    struct CHGTABLE
    {
    	std::vector<int> clr;
        ...
    };
    
    ...
    Elm e;
    CData Sen;
    ...
    auto elmnew = [&,e](auto obj){
        auto tmpe = std::make_unique<Elm>(e);
        return [&,tmpe0=std::move(tmpe)]() mutable{
            tmpe0->hclr = CHGTABLE.clr[obj.m_Color];
            return *tmpe0;
        };
    };
    ...
    Elm Senelm = elmnew(Sen); //-->

    ラムダ式を用いて値を変更することをしたいのですが、//ーー>の部分において、

    "lambda[]Elm() mutable->Elm"から、"Elm"への適切なユーザー定義変換が存在しません

    とエラーが出ます。

    お忙しいところ恐縮ですが、ラムダ式の場合の定義変換方法をご教示いただけますと幸いです。

    どうぞ宜しくお願い致します。



    • 編集済み SHIN109 2021年8月17日 2:17 戻す変数名を修正
    2021年8月6日 7:22

回答

  • SHIN109さん、こんにちは。フォーラムオペレーターのKumoです。
    MSDNフォーラムにご投稿くださいましてありがとうございます。

    ラムダ関数でコピーによってキャプチャされた変数の値を変更したいのでしょうか。
    そうであれば、私の知る限りでは、できないかと思います。

    具体的にはC++ でのラムダ式をご参照ください。

    通常、ラムダの関数呼び出し演算子は const-by-value ですが、mutableキーワードを使用するとこれを取り消します。mutableデータ メンバーは生成できません。 
    mutable仕様を使用すると、ラムダ式の本体で、値によってキャプチャされる変数を変更できます。
    mutable ではコピーを変更できますが、元のコピーは変更できません。

    例えば:

    #include <iostream>
    
    using namespace std;
    
    int main()
    {
    size_t t = 9;
    auto f = [t] () mutable {return ++t; };
    cout << f() << endl;
    cout << f() << endl;
    cout << "t:" << t << endl;
    return 0;
    }

    ここでは、値によってキャプチャされた変数tは、最初にキャプチャされた初期値が9であり、fを1回呼び出した後、10になります。再度呼び出されると、11になります。ただし、main()関数で定義されている最終出力tは値キャプチャであるため、その値は変更されず、最終的に9が出力されます。


    どうぞよろしくお願いいたします。 


    MSDN/ TechNet Community Support Kumo ~参考になった投稿には「回答としてマーク」をご設定ください。なかった場合は「回答としてマークされていない」も設定できます。同じ問題で後から参照した方が、情報を見つけやすくなりますので、 ご協力くださいますようお願いいたします。また、MSDNサポートに賛辞や苦情がある場合は、MSDNFSF@microsoft.comまでお気軽にお問い合わせください。~

    • 回答としてマーク SHIN109 2021年8月17日 6:25
    2021年8月13日 8:02
    モデレータ

すべての返信

  • ラムダ式の中のreturn文は何を返し、ラムダ式全体としてはどのような処理をしたいのでしょうか?

    現状のコードは、変換を行う関数オブジェクト(ラムダ式)を返そうとしています。しかし、質問内容を読む限り、変換結果を求めているようにも読めます。

    2021年8月6日 8:03
  • 佐祐理 様

    いつもお世話になっております。ありがとうございます。
    レスありがとうございました。

    失礼しました。要は、Elm e;を一時的に変更したeを返したいです。

    auto elmnew = [&,e](auto obj) mutable{
            e.hclr = CHGTABLE.clr[obj.m_Color];
            return e;
    };

    間違っていますが、あっさりとはこういうことでした。

    どうぞ宜しくお願い致します。


    2021年8月6日 13:00
  • この修正により、エラーメッセージも変わってきて、それによりこのフォーラムで尋ねたい内容も変わってくるのではありませんか? ただラムダ式を訂正すれば済む話ではないと思います。
    2021年8月6日 13:24
  • 佐祐理 様

    レスありがとうございました。


    記載しておりませんでしたが、
    Elm e;には既にデフォルト値が入っており、コピーキャプチャをすることでその時点での値を一時的に変更して使い、
    また渡すオブジェクトも出来ればとっかえひっかえしたいなという発想でした。

    しかし、今、おっしゃる意味が分かっておらず、恐らく分からないからこそ、このような質問になっているのだろうと思います。
    誠に申し訳ございませんが、その意味をご教示いただけませんでしょうか。

    お手数をおかけしますが、どうぞ宜しくお願い致します。
    2021年8月9日 2:15
  • SHIN109さん、こんにちは。フォーラムオペレーターのKumoです。
    MSDNフォーラムにご投稿くださいましてありがとうございます。

    ラムダ関数でコピーによってキャプチャされた変数の値を変更したいのでしょうか。
    そうであれば、私の知る限りでは、できないかと思います。

    具体的にはC++ でのラムダ式をご参照ください。

    通常、ラムダの関数呼び出し演算子は const-by-value ですが、mutableキーワードを使用するとこれを取り消します。mutableデータ メンバーは生成できません。 
    mutable仕様を使用すると、ラムダ式の本体で、値によってキャプチャされる変数を変更できます。
    mutable ではコピーを変更できますが、元のコピーは変更できません。

    例えば:

    #include <iostream>
    
    using namespace std;
    
    int main()
    {
    size_t t = 9;
    auto f = [t] () mutable {return ++t; };
    cout << f() << endl;
    cout << f() << endl;
    cout << "t:" << t << endl;
    return 0;
    }

    ここでは、値によってキャプチャされた変数tは、最初にキャプチャされた初期値が9であり、fを1回呼び出した後、10になります。再度呼び出されると、11になります。ただし、main()関数で定義されている最終出力tは値キャプチャであるため、その値は変更されず、最終的に9が出力されます。


    どうぞよろしくお願いいたします。 


    MSDN/ TechNet Community Support Kumo ~参考になった投稿には「回答としてマーク」をご設定ください。なかった場合は「回答としてマークされていない」も設定できます。同じ問題で後から参照した方が、情報を見つけやすくなりますので、 ご協力くださいますようお願いいたします。また、MSDNサポートに賛辞や苦情がある場合は、MSDNFSF@microsoft.comまでお気軽にお問い合わせください。~

    • 回答としてマーク SHIN109 2021年8月17日 6:25
    2021年8月13日 8:02
    モデレータ
  • フォーラムオペレーター Kumo 様


    レス、ありがとうございます。


    知識が乏しく、誤解を生む質問ばかりで申し訳ございません。


    調査中にmutableすることを知り、進めながらよく理解していない箇所(unique_ptrのスコープでdeleteされること等)が重なり、難しく考え混乱していた状態だと分かってきました。
    その状態でしたので、質問内容も提示するサンプルコードも意味不明になって、佐祐理様の仰るところではないかと思います。


    コピー元は変更せずに、コピーを変更して使用するという意味合いで、仰る通りです。
    リンクもありがとうございました。


    結論としては、佐祐理様への回答で記載した
    auto elmnew = [&,e](auto obj) mutable{
            e.hclr = CHGTABLE.clr[obj.m_Color];
            return e;
    };
    の形で出来ました。



    佐祐理 様

    大変失礼しました。レスありがとうございました。



    お二方、お忙しい中、ご教示ありがとうございました。
    いつもお手数お掛けして申し訳ありませんが、今後ともどうぞ宜しくお願いいたします。
    2021年8月17日 6:25