int
数値型 ( 、double
、float
など)のみをテンプレートとして受け入れるクラス テンプレートを作成するにはどうすればよいですか?
2 に答える
std::is_arithmetic
型特性を使用できます。そのようなタイプのクラスのインスタンス化のみを有効にしたい場合は、以下と組み合わせて使用しstd::enable_if
ます。
#include <type_traits>
template<
typename T, //real type
typename = typename std::enable_if<std::is_arithmetic<T>::value, T>::type
> struct S{};
int main() {
S<int> s; //compiles
S<char*> s; //doesn't compile
}
enable_if
の使いやすいバージョンと の無料追加については、この件に関する素晴らしい記事disable_if
を読むことを強くお勧めします。
C++ では、上記の手法には「置換の失敗はエラーではない」という名前があります (ほとんどの場合、頭字語 SFINAE が使用されます)。この C++ 手法の詳細については、wikipediaまたはcppreference.comを参照してください。
C++20 では、概念によってこれがはるかに簡単になり、インターフェイスが台無しになりません。
#include <concepts>
template<typename T>
concept arithmetic = std::integral<T> or std::floating_point<T>;
template<typename T>
requires arithmetic<T>
struct S{};
// Shorthand: template<arithmetic T> struct S {};
ただし、算術的に使用することを意図した多くのユーザー型があることに注意してください。そのため、探している型ではなく、探している操作をカバーするより一般的な概念が汎用インターフェイスで望ましいでしょう。
アプローチから受け取ったエラーメッセージはtemplate<typename T, typename = ...>
非常に不可解であることがわかりました(VS 2015)がstatic_assert
、同じ型特性を持つ a も機能し、エラーメッセージを指定できることがわかりました:
#include <type_traits>
template <typename NumericType>
struct S
{
static_assert(std::is_arithmetic<NumericType>::value, "NumericType must be numeric");
};
template <typename NumericType>
NumericType add_one(NumericType n)
{
static_assert(std::is_arithmetic<NumericType>::value, "NumericType must be numeric");
return n + 1;
}
int main()
{
S<int> i;
S<char*> s; //doesn't compile
add_one(1.f);
add_one("hi there"); //doesn't compile
}