How to ensure that the template parameter is a subtype of a desired type?
Given some complete type MyBase
, the following will yield a compile-time error if T
is not derived from MyBase
:
#include <boost/type_traits/is_base_of.hpp>
#include <boost/static_assert.hpp>
template<typename T>
class Foo {
BOOST_STATIC_ASSERT_MSG(
(boost::is_base_of<MyBase, T>::value),
"T must be a descendant of MyBase"
);
// Foo implementation as normal
};
If you're using a C++03 compiler with TR1, you can use std::tr1::is_base_of
instead of boost::is_base_of
; if you're using a C++11 compiler, you can use std::is_base_of
instead of boost::is_base_of
and the static_assert
keyword instead of the BOOST_STATIC_ASSERT_MSG
macro:
#include <type_traits>
template<typename T>
class Foo {
static_assert(
std::is_base_of<MyBase, T>::value,
"T must be a descendant of MyBase"
);
// Foo implementation as normal
};
N.b. this will yield true_type
for privately and ambiguously-derived types, so this is insufficient if what you really need is to treat T
as-a MyBase
(in most contexts).
Doc links:
Boost.StaticAssert
Boost.TypeTraits
Restrict C++ Template Parameter to Subclass
In this case you can do:
template <class T> void function(){
Baseclass *object = new T();
}
This will not compile if T is not a subclass of Baseclass (or T is Baseclass).
C++ 11 template sub type
I may not fully understand the question, but it seems if you change
SubTypeImpl SubType;
to
typedef SubTypeImpl SubType;
you can achieve what you want.
C++'s version of ? extends AnotherClass
You can static_assert(std::is_base_of<Base, T>::value, "Argument must extend base!");
.
However, note that relative to doing this in Java, in C++ this is nearly totally worthless. There's practically no use case that actually needs it.
C++: How to require that one template type is derived from the other
A trait you want might look like this:
template <typename B, typename D>
struct is_base_of // check if B is a base of D
{
typedef char yes[1];
typedef char no[2];
static yes& test(B*);
static no& test(...);
static D* get(void);
static const bool value = sizeof(test(get()) == sizeof(yes);
};
Then you just need a static assert of some sort:
// really basic
template <bool>
struct static_assert;
template <>
struct static_assert<true> {}; // only true is defined
#define STATIC_ASSERT(x) static_assert<(x)>()
Then put the two together:
template<class R1, class R2>
bool operator==(Manager<R1> m1, Manager<R2> m2)
{
STATIC_ASSERT(is_base_of<R1, R2>::value || is_base_of<R2, R1>::value);
return p1.internal_field == p2.internal_field;
}
If one does not derive from the other, the function will not compile. (Your error will be similar to "static_assert<false>
not defined", and it will point to that line.)
How to define a variantx,y,z extracting subtypes of a template parameter
There are two separate tasks:
- Extracting the states from the transition-table. This is easily done with pattern-matching.
- Removing duplicates. This can be done with O(log n) depth, the complexity comes from
std::tuple_cat
which usesstd::index_sequence
, and additionally directly from the latter.
Code for merging type-lists thrown in as a bonus:
#include <tuple>
#include <utility>
#include <type_traits>
namespace detail {
template <template <class...> class TT, template <class...> class UU, class... Us>
auto pack(UU<Us...>)
-> std::tuple<TT<Us>...>;
template <template <class...> class TT, class... Ts>
auto unpack(std::tuple<TT<Ts>...>)
-> TT<Ts...>;
template <std::size_t N, class T>
using TET = std::tuple_element_t<N, T>;
template <std::size_t N, class T, std::size_t... Is>
auto remove_duplicates_pack_first(T, std::index_sequence<Is...>)
-> std::conditional_t<(... || (N > Is && std::is_same_v<TET<N, T>, TET<Is, T>>)), std::tuple<>, std::tuple<TET<N, T>>>;
template <template <class...> class TT, class... Ts, std::size_t... Is>
auto remove_duplicates(std::tuple<TT<Ts>...> t, std::index_sequence<Is...> is)
-> decltype(std::tuple_cat(remove_duplicates_pack_first<Is>(t, is)...));
template <template <class...> class TT, class... Ts>
auto remove_duplicates(TT<Ts...> t)
-> decltype(unpack<TT>(remove_duplicates<TT>(pack<TT>(t), std::make_index_sequence<sizeof...(Ts)>())));
}
template <template <class...> class TT, class... Ts>
using merge_t = decltype(detail::unpack<TT>(std::tuple_cat(detail::pack<TT>(std::declval<Ts>())...)));
template <class T>
using remove_duplicates_t = decltype(detail::remove_duplicates(std::declval<T>()));
Applying it to your transitions-table:
template <template <class...> class TT, class ... Ts>
auto extract_states(TT<Ts...>)
-> TT<typename Ts::entry_state..., typename Ts::next_state...>;
using extracted = decltype(extract_states(std::declval<table>()));
using states = remove_duplicates_t<extracted>;
See it live on coliru.
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.]
Use Boost to ensure template argument inherits from some class
Try with
BOOST_STATIC_ASSERT(( boost::type_traits::is_base_of< ExceptionBaseClass, T >::value ));
It internally does the same check that @Zolyomi posted in his answer.
Related Topics
Finding Nearest Point in an Efficient Way
How to Use Boost Preprocessor to Generate Accessors
Issue with Cin When Spaces Are Inputted, Using String Class
Array Decay to Pointers in Templates
Operator Overload Which Permits Capturing with Rvalue But Not Assigning To
Using Boost::Iostreams::Mapped_File_Source with Std::Multimap
Differencebetween Cout, Cerr, Clog of iOStream Header in C++? When to Use Which One
Performance Hit from C++ Style Casts
Why Does 'Int ;' Compile Fine in C, But Not in C++
Sine Wave That Slowly Ramps Up Frequency from F1 to F2 for a Given Time
C Function Pointers with C++11 Lambdas