先日の yhpg の懇親会で、関数へのポインタをテンプレート引数にできるという話を聞いた。
私はてっきり無理だと思っていたんだけど、テンプレートの黎明期からできた模様:
このほかの template-arg は、 constant-expression(定数式)であるか、外部リンケージのオブジェクトや関数、あるいは静的クラス・メンバのアドレスでなければならない。
( 注解 C++リファレンスマニュアル p430 )
知らなかった。
まあ知っていても使う機会はなかなかなさそうではあるけれど。
関数へのポインタをテンプレート引数にする
例えば以下のような感じ。
ptrtemplate1.cpp
// clang++ -std=c++11 ptrtemplate1.cpp
# include <iostream>
template< char const *func()>
void foo()
{
std::cout << "FOO[" << func() << "]\n";
}
char const * bar()
{
return "bar";
}
int main()
{
foo<bar>(); //=> FOO[bar]
}
グローバル変数へのポインタをテンプレート引数にする
グローバル変数へのポインタはテンプレート引数にできるが、ローカルな変数はテンプレート引数にできない。
以下の通り:
ptrtemplate2.cpp
// clang++ -std=c++11 ptrtemplate2.cpp
# include <iostream>
char const * bar = "bar";
template< char const ** str >
void foo()
{
std::cout << "FOO[" << *str << "]\n";
}
int main()
{
foo<&bar>(); //=> FOO[bar]
char const * baz = "baz";
foo<&baz>(); //=> エラー。
}
メンバへのポインタをテンプレート引数にする
注解 C++リファレンスマニュアル の記述からはわからないが、メンバへのポインタもテンプレート引数にすることができる。
以下の通り:
ptrtemplate3.cpp
// clang++ -std=c++11 ptrtemplate3.cpp
# include <iostream>
struct Hoge
{
char const * fuga;
char const * piyo;
};
Hoge hoge()
{
return { "fuga", "piyo" };
}
template< char const * Hoge::*m >
void foo()
{
std::cout << "FOO[" << (hoge().*m) << "]\n";
}
int main()
{
foo<&Hoge::fuga>(); //=> Foo[fuga]
foo<&Hoge::piyo>(); //=> Foo[piyo]
}
いずれも
いずれも、なかなか使い所のない機能だと思う。