この質問は別の質問のフォローアップです。
次のコードを検討してください。
template<typename F>
struct S;
template<typename Ret, typename... Args>
struct S<Ret(Args...)> { };
template<typename... Args>
using Alias = S<void(Args...)>;
int main() {
S<void(void)> s; // (1)
Alias<void> alias; // (2)
}
(2)をコメントアウトすると、例は準拠します。そうしないと、コンパイルは失敗します。リンクされた質問から、 (2)が次の理由で失敗することが
わかります。
非依存型 void の単一の名前のないパラメーターで構成されるパラメーター リストは、空のパラメーター リストと同等です。この特殊なケースを除いて、パラメーターは typecv void を持ってはなりません。
さらに:
[注: 型推定は、次の理由で失敗する可能性があります: — [...] — パラメーターの型が void である関数型、または戻り値の型が関数型または配列型である関数型を作成しようとしています。— [...] —エンドノート]
私には明らかではないのは、(1)がコンパイルされる理由です。
言い換えると、(2)Args
が依存型であり、上記の制限に悩まされているために失敗した場合:
template<typename... Args>
using Alias = S<void(Args...)>;
同じ問題が以下に影響Args
するはずです。
template<typename Ret, typename... Args>
struct S<Ret(Args...)> { };
この場合のように使用void
しても問題ないのはなぜですか?
ラッシュは、この種の署名も受け入れる に向けられていることに注意してください。S<void(void)>
std::function