95198
言語: C++  
C++: 17  
IDE: Qt Creator 10.0.1  
Qt: 6.4.3  
コンパイラ: MSVC 2019, x86_64

いくつかのgetter/setterが定義されたクラスがあります。

```

    class detect_gravity {
    private:
        cv::Point2i _gravity_point;
        cv::Point2i _decimation;
        int32_t _level;
    
    public:
        const cv::Point2i &gravity_point() const { return _gravity_point; }
        const cv::Point2i &decimation() const { return _decimation; }
        void decimation(const cv::Point2i &value) { _decimation = value; }
        int32_t level() { return _level; }
        void level(const int32_t &value) { _level = value; }
    };
    
```

このようなクラスが複数種類あり、プロパティの型も様々です。  
これらのgetter/setterをすべて同じ型にして変数に格納したいと考えています。

例えば、  
getterは`std::function<const void*(void*)>`の形で  
戻り値は取得した値へのポインタ、引数はプロパティを持つクラスのインスタンスへのポインタ。  
(ここでは'detect_gravity'クラスのインスタンス)

setterは`std::function<void(void*, const void*)>`の形で、  
第1引数はクラスインスタンスへのポインタ、第2引数は設定する値へのポインタ。

そして、それらをプロパティの管理クラスへ登録します。  
登録時は以下の様に書きます。(decimationプロパティの場合)

```

    config.register_property(
        "プロパティ名", "プロパティの説明",
        make_getter<const cv::Point2i &() const>(&detect_gravity::decimation),
        make_setter<void(const cv::Point2i&)>(&detect_gravity::decimation));
    
```

make_getterおよびmake_setterは下記の通りです。

```

    template <class _Rx, class _Ty>
    proc_system::getter_t make_getter(_Rx _Ty::*getter) {
        return [getter](void *obj) -> const void* {
            _Ty *pobj = static_cast<_Ty*>(obj);
            auto &val = (pobj->*getter)();
            return static_cast<const void*>(&val);
        };
    }
    
    template <class _Rx, class _Ty, class _Arg>
    proc_system::setter_t make_setter(_Rx (_Ty::*setter)()) {
        return [setter](void* obj, const void* val){
            auto pobj = static_cast<_Ty*>(obj);
            auto pval = static_cast<_Arg*>(val);
            (pobj->*setter)(*pval);
        };
    }
    
```

このとき、`make_setter<void(const cv::Point2i&)>(&detect_gravity::decimation)`の部分で

```

    エラー: No matching function for call to 'make_setter'
    
```

と出てしまいます。  
また、make_setter内では以下のエラーが出ています。

```

    Candidate template ignored: substitution failure [with _Rx = void (const cv::Point2i &)]:
    function cannot return function type 'void (const cv::Point2i &)' (aka 'void (const Point_<int> &)')
    
```

上記のエラーはなぜ起こっているのでしょうか？
CC BY-SA 4.0
2023-06-13T00:30:06.437
95194
2023-06-13T20:56:24.393
53943
question
c++
関数テンプレートにメンバ関数ポインタを渡したときに"No matching function for call to '*'"が発生する
`make_setter` の引数の型が，「引数無し」のメンバ関数になっていたりとか，いろいろと問題がありますね．

当該引数が参照である場合，「参照のポインタ」はダメなので，そこも対処する必要がありそうです．

`make_setter` template を使う箇所の文法も明らかに間違っています．

```

    using setter_t = std::function<void(void*, const void*)>;
    
    //こんなのでとりあえずいけるかも？
    template < class Rx, class Ty, class Arg >
    setter_t make_setter( Rx (Ty::*setter)(Arg) ) {  //←引数が要るよね
        return [setter](void* obj, const void* val){
            auto pobj = static_cast<Ty*>(obj);
            auto pval = static_cast< std::remove_reference_t<Arg> * >(val);  //←Argが参照だったらどうするのか，というのが要る
            (pobj->*setter)(*pval);  //←ココ，Rx は常に捨てる？
        };
    }
    
    //使う側：template型引数というのはこのように指定するのでは
    make_setter<void,detect_gravity,const cv::Point2i&>(&detect_gravity::decimation);
    
```

＃関係ないけど，こういうのをどこぞに登録できたとして，どうやって正しく使うんだろう？
CC BY-SA 4.0
2023-06-13T01:51:50.633
95198
2023-06-13T01:51:50.633
52236
95194
answer