テンプレートクラスに問題があります。 スタック、それは動作しますでクラスをインスタンス化するとき。同じクラスをヒープでインスタンス化すると失敗します。(引数の推論)理由がわかりません...
情報: 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を回避する解決策はありますか?
おかげで、
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
は避けられません。タイプエイリアスを導入して、不便を軽減してください。
最新のgccとclangでは動作します-これはnew MethodPtr(ptr, func)
です。したがって、gcc7.2の場合-これはバグです。
unique_ptr(new MethodPtr(ptr, func))
の場合-機能しません-C++では-このレベルではMethodPtr*
があるため、unique_ptr<MethodPtr[]>
とunique_ptr<MethodPtr>
を区別できないため、推定できません。
こちら を見てください。 MethodPtr
(クラステンプレート)を関数テンプレート(_std::make_unique
_)の非テンプレートタイプのパラメーターとして単純に渡すことは決して許可されておらず、クラステンプレート引数の演繹はそれを変更しませんでした。
_new MethodPtr{ptr, func};
_はリファレンスを参照することで機能しますが、それがnew MethodPtr(ptr, func);
と異なる必要がある理由はわかりません