web-dev-qa-db-ja.com

テンプレートの控除はヒープで失敗しましたが、スタックでは機能します

テンプレートクラスに問題があります。 スタック、それは動作しますでクラスをインスタンス化するとき。同じクラスをヒープでインスタンス化すると失敗します。(引数の推論)理由がわかりません...

情報: c ++ 17でgcc 7.2.0を使用しています。

ここに例:

#include <iostream>
#include <cstdlib>
#include <memory>

template <class ReturnType, class ClassName, class... Args>
class MethodPtr
{
public:
    typedef ReturnType (ClassName::*Method)(Args...);

    MethodPtr(ClassName* ptr, Method m) : _p(ptr), _m(m)
    {
        (ptr->*m)(4);
    }

    ClassName* _p;
    Method _m;
};

class Example
{
public:
    Example()
    {
        dotest(this, &Example::func);
    }

    template <class Ptr, class Func>
    void dotest(Ptr ptr, Func func)
    {
        // works
        MethodPtr(ptr, func);

        // don't works
        //std::make_unique<MethodPtr>(ptr, func);
        //new MethodPtr(ptr, func);

        //works
        std::make_unique<decltype(MethodPtr(ptr, func))>(ptr, func);
        new decltype(MethodPtr(ptr, func))(ptr, func);
    }

    void func(int i)
    {
        std::cout << i << std::endl;
    }
};

int main()
{
    Example example;
}

Decltypeを回避する解決策はありますか?

おかげで、

26
user9098083

new MethodPtr(ptr, func)が演繹に失敗するという事実は、コンパイラのバグです。 [dcl.type.class.deduct]/2 によれば:

推定クラスタイプのプレースホルダーは、type-specifier-seqnew-type-idまたはtype-idでも使用できます。 new-expressionの場合、または明示的な型変換(関数表記)([expr.type.conv])のsimple-type-specifierとして。推定クラスタイプのプレースホルダーは、他のコンテキストでは表示されません。

ご覧のとおり、新しい式の明示的なyesと、明示的に許可されていないものの全面禁止です。そう make_uniqueできませんプレースホルダーを指定できません。

これが修正されたGCCバージョンに移行できない場合(またはmake_unique)、decltypeは避けられません。タイプエイリアスを導入して、不便を軽減してください。

21
StoryTeller

最新のgccとclangでは動作します-これはnew MethodPtr(ptr, func)です。したがって、gcc7.2の場合-これはバグです。

unique_ptr(new MethodPtr(ptr, func))の場合-機能しません-C++では-このレベルではMethodPtr*があるため、unique_ptr<MethodPtr[]>unique_ptr<MethodPtr>を区別できないため、推定できません。

6
PiotrNycz

こちら を見てください。 MethodPtr(クラステンプレート)を関数テンプレート(_std::make_unique_)の非テンプレートタイプのパラメーターとして単純に渡すことは決して許可されておらず、クラステンプレート引数の演繹はそれを変更しませんでした。

_new MethodPtr{ptr, func};_はリファレンスを参照することで機能しますが、それがnew MethodPtr(ptr, func);と異なる必要がある理由はわかりません

3
LogicStuff