テンプレート クラス内の関数で、プリミティブ型とそれ以外を区別しようとしています。
C++ 11 では、次のことができます。
if(std::is_fundamental<T>::value)
{
// Treat it as a primitive
}
else
{
//Treat it otherwise
}
私が間違っている場合は修正してください。これは c++ 11 だけではありません。
以前のバージョンの C++ でこれに代わるものはありますか?
テンプレート クラス内の関数で、プリミティブ型とそれ以外を区別しようとしています。
C++ 11 では、次のことができます。
if(std::is_fundamental<T>::value)
{
// Treat it as a primitive
}
else
{
//Treat it otherwise
}
私が間違っている場合は修正してください。これは c++ 11 だけではありません。
以前のバージョンの C++ でこれに代わるものはありますか?
次のように、C++03 でBoost の型特性を使用できます。
#include <boost/type_traits/is_fundamental.hpp>
...
if(boost::is_fundamental<T>::value)
{
// Treat it as a primitive
}
else
{
//Treat it otherwise
}
これは C++98 でも機能するはずです。
このコードを使用すると、問題が発生する可能性があります。異なる型特性を区別する必要がある場合は、実行時ではなくコンパイル時に行う必要があります。実行している操作によっては、2 つのブランチのいずれかがif
コンパイルされない場合があります。したがって、特殊な関数に転送することをお勧めします。
void operation_impl(boost::true_type /*other params*/) {
// Treat it is primitive
}
void operation_impl(boost::false_type /*other params*/) {
// Treat it otherwise
}
template<class T>
void operation(/* params*/) {
operation_impl(boost::is_fundamental<T>::type() /*other params*/);
}
この実装手法では、使用されたブランチのみをコンパイルする必要があります (つまり、正しい)。
編集:
ここにいくつかの追加情報があります。この問題の解決策は、テンプレートのインスタンス化に関係しています。is_fundamental
からに切り替えて、is_array
操作がどのように失敗するかを示します。
最初の例から始めましょう:
template <class T>
void fun(T t) {
if(boost::is_array<T>::value)
{
std::cout << "true" << std::endl;
}
else
{
std::cout << "false" << std::endl;
}
}
void f(int i) {
fun(i);
}
コンパイルして実行すると、コンパイラは if ステートメントの 1 つの分岐のみが使用されることを確認し、他の分岐を未使用のコードとして削除します。
2 番目の例では、配列操作を使用する場合に何かを行います。
template<class T>
void fun(T& t) {
if(boost::is_array<T>::value)
{
std::cout << t[0];
}
else
{
std::cout << t;
}
}
void f(int i) {
fun(i);
}
今はコンパイルされません。その理由は、テンプレート引数としての int の形式が正しくないためですt[0]
。このランタイム ステートメントを使用して、コンパイル時にコードで必要な型プロパティを区別することはできません (この例では、配列のプロパティと の使用t[0]
)。
3 番目の例では、関数のオーバーロードによってコンパイル時間を区別します。
template<class T>
void fun_impl(boost::true_type, T& t) {
std::cout << t[0];
}
template<class T>
void fun_impl(boost::false_type, T& t) {
std::cout << t;
}
template<class T>
void fun(T& t) {
fun_impl(typename boost::is_array<T>::type(),t);
}
void f(int i) {
fun(i);
}
ここでis_array<T>::type
は または のいずれtrue_type
かfalse_type
です。この結果はfun_impl
、コンパイル時に適切なオーバーロードを選択するためのセレクターとして使用され、選択されたオーバーロードのみがインスタンス化されてコンパイルされます。
通常、このような手法は、型が特定のプロパティを持っている場合にのみコンパイル可能な最適な実装をコンパイル時に選択するために使用されます。
2回目の編集:
static if
言語の一部である場合、これはもちろん変更されます。