header for optionally-lazy parameters(GitHub repositoryにも表示されています)を作成しました。 (これはnot my first question based on the headerです)仮想デストラクタはdecltypeの動作を変更します
私は基本クラスのテンプレートと2つの派生クラスのテンプレートを持っています。基底クラスのテンプレートはstatic_assert
のprotected
コンストラクタを持ちます。このコンストラクタは、特定の派生クラスによってのみ呼び出されます。 static_assert
の中に私はdecltype
を使用しています。
本当に奇妙な事がdecltype
内部名のタイプは何とか私の基本クラステンプレートの仮想デストラクタがあるかどうかによって影響されることです。デストラクタがコメントアウトされている場合、これはエラーなしでコンパイルされることを
#include <type_traits>
#include <utility>
template <typename T>
class Base
{
protected:
template <typename U>
Base(U&& callable)
{
static_assert(
std::is_same<
typename std::remove_reference<decltype(callable())>::type, T
>::value,
"Expression does not evaluate to correct type!");
}
public:
virtual ~Base(void) =default; // Causes error
virtual operator T(void) =0;
};
template <typename T, typename U>
class Derived : public Base<T>
{
public:
Derived(U&& callable) : Base<T>{std::forward<U>(callable)} {}
operator T(void) override final
{
return {};
}
};
void TakesWrappedInt(Base<int>&&) {}
template <typename U>
auto MakeLazyInt(U&& callable)
{
return Derived<
typename std::remove_reference<decltype(callable())>::type, U>{
std::forward<U>(callable)};
}
int main()
{
TakesWrappedInt(MakeLazyInt([&](){return 3;}));
}
注:
は、ここに私のMCVEです。
callable
はの式になり、()
演算子で呼び出されたときにはT
の何かが返されます。 Base
に仮想デストラクタがなければ、これは正しく評価されているようです。 との仮想デストラクタを使用すると、callabele
のタイプはBase<T>
であることがわかります(私の言う限り、意味をなさない)。
recursive_lazy.cpp:13:55: error: type 'Base<int>' does not provide a call operator
typename std::remove_reference<decltype(callable())>::type, T
^~~~~~~~
recursive_lazy.cpp:25:7: note: in instantiation of function template specialization
'Base<int>::Base<Base<int> >' requested here
class Derived : public Base<T>
^
1 error generated.
EDIT:=delete
コピーコンストラクタを-ing
recursive_lazy.cpp: In instantiation of ‘Base<T>::Base(U&&) [with U = Base<int>; T = int]’:
recursive_lazy.cpp:25:7: required from ‘auto MakeLazyInt(U&&) [with U = main()::<lambda()>]’
recursive_lazy.cpp:48:47: required from here
recursive_lazy.cpp:13:63: error: no match for call to ‘(Base<int>)()’
typename std::remove_reference<decltype(callable())>::type, T
はここクラン++ 3.7のエラーメッセージです: は、ここでG ++ 5.1のエラーメッセージですもこのエラーを引き起こします。
'r値をとる(U &&呼び出し可能)私は奇妙な仮想デストラクタエラーをご紹介できなかったが、私は'派生いることがわかりユニバーサルリファレンスではありません。それは意図されていますか? – SirGuy
何をするべきかを示す例にいくつかの出力を追加できますか? TakesWrappedIntは、最後の演算子T();のためにあなたの例でゼロになるようです。 –
@GuyGreerいいえ、それは意図されていません。これは、いったんテンプレートが特殊化されると、Uはもはやテンプレートタイプではないからですか? –