質問: vectorやarrayなどを気にせず標準出力がしたく、以下のようなコードを記述しました。 ``` // 一次元配列用(のつもり) // 二次元配列でも該当してしまう template auto f(T&& range) -> decltype(std::begin(range), std::end(range), range.back(), void()) { for (const auto& r : range) { if (&r != &range.back()) std::cout << r << " "; else std::cout << r << std::endl; } } // 二次元配列用 template auto f(T&& range) -> decltype(std::begin(range), std::end(range), range.back(), std::begin(range.at(0)), std::end(range.at(0)), range.at(0).back(), void()) { for (const auto& r : range) { for (const auto& a : r) { if (&a != &r.back()) std::cout << a << " "; else std::cout << a << std::endl; } } } int main() { std::vector vec(3, 99); f(vec); std::array arr{99, 99, 99, 99}; f(arr); //std::vector> vec2(3, vec); //f(vec2); return 0; } ``` 以上のコードでfに二次元配列を渡すと複数当てはまってしまいます。 うまく失敗させる方法はありますか?
回答: こんにちは。 関数テンプレートは、クラス・テンプレートと異なり「プライマリー・テンプレート」がないのでテンプレート間の優先順位は(あまり)ついていません。ですので、基本的には厳密に判定させる必要があります。 つまり、1次元配列は「指定の型が配列で、その要素が配列でない」、多次元配列は「指定の型が配列で、その要素も配列である」を指定する必要があります。 ですので、ご希望の実装のためには、is_containerのようなメタ処理を記述し、enabler方式で関数テンプレートの合致条件を記述するのが良いと思います。