Template Constraints C++
As someone else has mentioned, C++0x is getting this built into the language. Until then, I'd recommend Bjarne Stroustrup's suggestions for template constraints.
Edit: Boost also has an alternative of its own.
Edit2: Looks like concepts have been removed from C++0x.
Use C++20 Concept to constrain template parameter
The correct syntax for the partial template specialization for constraints should be:
template<typename T>
concept smallerThanPointer = sizeof(T) < sizeof(void*);
template<class T>
class MyClass
{
public:
MyClass() { std::cout << "MyClass[...]\n"; }
};
template<class T> requires smallerThanPointer<T>
class MyClass<T>
{
public:
MyClass() { std::cout << "MyClass[smallerThanPointer]\n"; }
};
Demo.
How to constraint a template to be iterable ranges using concepts?
I am trying to learn how to use concepts in C++, so is there some way I can use
concept
here to make sure T is iterable?
You can have standard concept std::ranges::range
from <ranges>
header here. With that your function will look like:
#include <ranges> // std::ranges::range
template<std::ranges::range T>
decltype(auto) find_median_sorted(T const& container) {
// some code here
}
To restrict the ranges to be only for random access iterable ranges, you can use either std::ranges::random_access_range
again from <ranges>
header
#include <ranges> // std::ranges::random_access_range
template<std::ranges::random_access_range T>
decltype(auto) find_median_sorted(T const& container) {
// some code here
}
or via iterator concept std::random_access_iterator
as follows:
#include <iterator> // std::random_access_iterator
template<typename T>
decltype(auto) find_median_sorted(T const& container)
requires std::random_access_iterator<std::ranges::iterator_t<T>>
{
// some code here
}
Constraint a template parameter to only accept std::vector and std::list with C++20 concepts
This:
template<typename T>
concept ValidContainer = requires(T a) {
std::same_as<T, std::vector<typename T::value_type>>;
std::same_as<T, std::list<typename T::value_type>>;
};
is checking to see if the expression std::same_as<T, std::vector<typename T::value_type>>;
is valid, not that it also is true
. Which is to say, it's basically just checking that typename T::value_type
is a thing.
In that form, if you want to require something, you have to use requires
:
template<typename T>
concept ValidContainer = requires(T a) {
requires std::same_as<T, std::vector<typename T::value_type>>;
requires std::same_as<T, std::list<typename T::value_type>>;
};
Although now we're requiring that T
is both a vector
and a list
, so that's never going to be true. So really we need:
template <typename T>
concept ValidContainer =
std::same_as<T, std::vector<typename T::value_type>>
|| std::same_as<T, std::list<typename T::value_type>>;
Although even this isn't great because now we're rejecting std::vector<T, MyAlloc>
.
This is separate from the question of why this is your constraint - why can you only sort vector
and list
... but not like deque
or string
or span
or ... ? Or why you're limiting to just int
and float
?
You can bubble sort any forward range that is orderable. Which I would express as:
template <std::ranges::forward_range R>
requires std::totally_ordered<std::ranges::range_reference_t<R>>
void BubbleSort(R& r);
C++ Template Method Type Constrained
Finally, I got something that makes exactly what I was searching for. It gives you the information on real-time of the error without having to build the solution. It is the most similar thing to C# I found. How works for you too.
//T must inherit from Actor
template<typename T>
typename std::enable_if<std::is_base_of<Actor, T>::value, T*>::type Create()
{
//Some code
return actor;
}
You can find more information about the std::enable_if here.
In addition, I have to say that the previous code wrote in the question worked fine for the people who have helped me, so maybe is a good solution for you.
C++ templates that accept only certain types
I suggest using Boost's static assert feature in concert with is_base_of
from the Boost Type Traits library:
template<typename T>
class ObservableList {
BOOST_STATIC_ASSERT((is_base_of<List, T>::value)); //Yes, the double parentheses are needed, otherwise the comma will be seen as macro argument separator
...
};
In some other, simpler cases, you can simply forward-declare a global template, but only define (explicitly or partially specialise) it for the valid types:
template<typename T> class my_template; // Declare, but don't define
// int is a valid type
template<> class my_template<int> {
...
};
// All pointer types are valid
template<typename T> class my_template<T*> {
...
};
// All other types are invalid, and will cause linker error messages.
[Minor EDIT 6/12/2013: Using a declared-but-not-defined template will result in linker, not compiler, error messages.]
Forward Declaration of Constrained Template Specializations
Was a bug; is now fixed. No idea which version this fix will make it into.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96363
Related Topics
Embed Text File in a Resource in a Native Windows Application
How to Print the Wchar_T Values to Console
Gdb Complaining About Missing Raise.C
Exporting a C++ Class from a Dll
How to Check If Given C++ String or Char* Contains Only Digits
Checking If a Directory Exists in Unix (System Call)
C++11 - Static_Assert Within Constexpr Function
Is There Any Reason to Use This-≫
Alternative Virtual Function Calls Implementations
How to Code a Modulo (%) Operator in C/C++/Obj-C That Handles Negative Numbers
Difference Between Undefined Behavior and Ill-Formed, No Diagnostic Message Required
Why Does Printf() Promote a Float to a Double
Why Switch/Case and Not If/Else If
C++ Obtaining Milliseconds Time on Linux - Clock() Doesn't Seem to Work Properly
Fast Ceiling of an Integer Division in C/C++
When Is Uint8_T ≠ Unsigned Char