次のコードを想定します。
#include <iostream>
template<typename... T>
void foo(const T &...);
template<unsigned N>
void foo(const char (&)[N])
{
std::cout << "char(&)[N]" << std::endl;
}
void foo(const char *)
{
std::cout << "const char *" << std::endl;
}
template<typename T>
void foo(const T &)
{
std::cout << "Single" << std::endl;
}
template<typename First, typename... T>
void foo(const First & first, const T &... rest)
{
std::cout << "Generic + " << sizeof...(T) << std::endl;
foo(first);
foo(rest...);
}
int main()
{
const char * c = "asdf";
char a[] = {'a', 'b', 'c', 'd'};
foo('f', c, a, 1);
foo(a);
}
Generic + 3
Single // fine; 'f' is `char` -> generic
Generic + 2
const char * // fine; c is `const char *`
Generic + 1
const char * // (!) not fine
Single
char(&)[N] // fine; a is char[4]
最後の呼び出し -foo(a)
でa
あるchar[4]
- は、私が期待しているバージョンを呼び出します - template<unsigned N> void foo(const char (&)[N])
。foo
しかし、 callの可変個引数テンプレートのインスタンス化ではなくfoo(const char (&)[N]
、foo(const char *)
代わりに呼び出すのはなぜですか? char 配列のオーバーロードがなければ、それは当然のことですが、なぜここで発生しているのでしょうか? const First &
配列型を適切にキャプチャするべきではありませんか?
また、渡された配列で一般的な可変個引数バージョンを適切に機能させる最も簡単な方法は何でしょうか?
Matthieu M.がコメントで気づいたように、この問題はおそらく可変個引数テンプレートではなく、indirectionによって引き起こされます。
#include <iostream>
template <unsigned N>
void foo(const char (&)[N])
{
std::cout << "char(&)[N]" << std::endl;
}
void foo(const char *)
{
std::cout << "const char *" << std::endl;
}
template <typename T>
void goo(T const& t) {
foo(t);
}
int main()
{
char a[] = {'a', 'b', 'c', 'd'};
foo(a);
goo(a);
}
文字(&)[N] const char *
彼はまた、それはコンパイラのバグかもしれないとも言いました - コードは Clang 3.2 dev、G++ 4.6 および 4.7 の両方でまったく同じ結果をもたらしますが。
R. Martinho Fernandesa
は、最後のスニペットで の型を に変更するとconst char a[]
、コードがconst char *
2 回生成されることに注意しました。