It is possible to restrict template parameter?
template <class T>
class myclass
{
...
}; For example I want that T might be int double or my own defined complex but nothing else!
Short summary and context: the usual 2009-era workarounds you see in this thread (compile-time asserts and hand-rolled trait specializations) are valid for old compilers — see and for examples — but modern C++ gives cleaner, safer options. Below are concise, practical patterns to restrict a template parameter to a specific list (for example: int, double, or a user type MyComplex).
A clean C++20 solution: use concepts (nice diagnostics and direct syntax). Example:
#include <concepts>
struct MyComplex { /* user-defined */ };
template<typename T>
concept AllowedT = std::same_as<T,int> || std::same_as<T,double> || std::same_as<T,MyComplex>;
template<AllowedT T>
class myclass { /* ... */ }; Concepts are the language-native way to constrain templates and produce readable error messages. (cppreference.com)
If C++20 is not available, use standard type-traits + SFINAE or a compile-time trait check. Two compact options:
std::enable_if_t (remove overloads you don't want), orstd::disjunction / a fold-expression and static_assert to fail early.Example (C++17+):
#include <type_traits>
struct MyComplex { /* ... */ };
template<typename T>
using is_allowed = std::disjunction<std::is_same<T,int>, std::is_same<T,double>, std::is_same<T,MyComplex>>;
template<typename T>
class myclass {
static_assert(is_allowed<T>::value, "T must be int, double, or MyComplex");
/* ... */
}; std::enable_if and trait helpers are the standard pre-concepts approach; std::disjunction and fold-expressions make the “list of allowed types” easy to express. (en.cppreference.com)
Practical notes: put the check where the class is instantiated so errors point to the caller; prefer concepts when the toolchain supports C++20 (better diagnostics); include <concepts> or <type_traits> as shown; if the allowed set may grow, encapsulate it in a single trait so maintenance is simple. For compile-time assertions, use static_assert (standard since C++11) for clear, immediate diagnostics. (cppreference.com)
Jump to Post— Narue 5,707Sadly, constraints are not a part of C++, and concepts (the design for constraints) have been dropped from the next revision of the standard. However, you can fake it using static assertions and template specialization:
#include <iostream> #define STATIC_ASSERT(condition) \ do \ char foo[condition] = {0}; \ …
Sadly, constraints are not a part of C++, and concepts (the design for constraints) have been dropped from the next revision of the standard. However, you can fake it using static assertions and template specialization:
#include <iostream>
#define STATIC_ASSERT(condition) \
do \
char foo[condition] = {0}; \
while ( false );
template <class T>
class myclass
{
public:
myclass() { enforce_constraint(); }
private:
void enforce_constraint()
{
STATIC_ASSERT ( false );
}
};
template<>
void myclass<int>::enforce_constraint() {}
int main()
{
myclass<double> a;
myclass<int> b;
} The error is uninformative, but that's because the static assertion is very simple and naive. There are better ways, such as Boost's static assert.
Posted in the correct thread this time. This is also another way, and still
naive. It shows both static_assertion and exceptions.
#include<iostream>
using namespace std;
template<typename Type>
struct assert_numeric{ const static int i = 0; };
template<> struct assert_numeric<short> { const static int i = 1; };
template<> struct assert_numeric<unsigned short> { const static int i = 1; };
template<> struct assert_numeric<int> { const static int i = 1; };
template<> struct assert_numeric<unsigned int> {const static int i = 1; };
template<> struct assert_numeric<float> { const static int i = 1; };
template<> struct assert_numeric<double> { const static int i = 1; };
template<typename Type>
class Numeric{
public:
struct BadType : std::exception{
BadType(const char *msg) : exception(msg){}
};
public:
Numeric()
{
//int asserter[assert_numeric<Type>::i];// Way# 1 cannot have an array of size 0
if(assert_numeric<Type>::i == 0) //Way number 2 : throw custom exception
throw BadType("Type is not numerical!");
}
~Numeric(){ }
};
int main()
{
try{
Numeric<char> j;
}
catch(Numeric<char>::BadType& e){ cout << e.what() <<endl; }
return 0;
} We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.