Template Constraints C++

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



Leave a reply



Submit