Eigen3 and built-in type inter-compatibility
Hello guys. I'm stuck with the problem of writing routines which can handle both Eigen3 types (Matrixes and Arrays) and built-in types. I can best explain this with an example: let's suppose I have a Meter<Type> template class which has the ability to collect statistics during runtime.
The Type class should support the following operators:
operator=(Scalar)
operator=(Type)
operator+(Type)
operator-(Type)
operator*(Type)
operator/(Type)
operator*(Scalar)
operator/(Scalar)
Eigen3 types provides all of these operators with two exceptions: first, the operator*(Type) represents a dot-preduct if Type is some subclass of Eigen::MatrixBase and represents a coefficient-wise product if Type is some subclass of Eigen::ArrayBase. I can easily workaround this; second, neither one implements an operator=(Scalar) required for ensuring the correct initialization to zero.
I tried implementing the following functor classes to help me take care of the distinction but I can't get them to work:
some structs to handle the distrinction between built-in types and Eigen3 types:
template < class _Type > struct is_scalar : true_type {
using Scalar = _Type;
using Type = _Type;
static constexpr bool value = true;
};
template < class _Matrix >
struct is_scalar<Eigen::MatrixBase<_Matrix>> : false_type {
using Scalar = typename Matrix::Scalar;
static constexpr bool value = false;
};
template < class _Array >
struct is_scalar<Eigen::ArrayBase<_Array>> : false_type {
using Scalar = typename Array::Scalar;
static constexpr bool value = false;
};
the function implementation itself
template < class Scalar, bool is_scalar = Math::is_scalar<Scalar>::value >
struct set_const_impl;
template < class Scalar >
struct set_const_impl< Scalar, true > {
static const void run(Scalar &_x, Scalar _y) noexcept { _x = _y; }
};
template < class EigenType >
struct set_const_impl<EigenType, false> {
template < class Scalar >
static const void run(Eigen::EigenBase<EigenType> &_x, Scalar _y) noexcept {
_x.derived().setConstant(_y);
}
};
template < class Type, class Scalar > void set_const(Type &_x, Scalar _y) noexcept {
set_const_impl<Type>::run(_x, _y);
}
template < class Type > void set_zero(Type &_x) noexcept {
set_const_impl<Type>::run(_x, 0);
}
The specialized version set_const_impl<EigenType> never gets instantiated. For example, if I call
Eigen::Matrix<double, 3, 1> m1;
set_zero(m1);
I get the compiler to complain at the 0 on the line
set_const_impl<Type>::run(_x, 0);
saying that 0 is not implicitly convertible to Eigen::Matrix<double, 3, 1>, which means it picked the set_const_impl<Scalar, true> version of the functor (where both arguments share a the common type Scalar). This also means that my is_scalar construction isn't working in this case, even if I've already used it and tested it on other classes without problems.
I need this behaviour in several other classes and I don't want to explicitly specialize each one of them! Anyone knows what should I do to fix this?
Thanks in advance for any help!
Your problem is your traits is_scalar which takes only base classes and not derived classes.
You may try something like:
namespace Helper
{
template <typename T> std::false_type is_scalar(const Eigen::MatrixBase<T>*);
template <typename T> std::false_type is_scalar(const Eigen::ArrayBase<T>*);
std::true_type is_scalar(...);
}
template<typename T>
struct is_scalar : decltype(Helper::is_scalar(std::declval<T*>()))
{};
I encounted the same problem, and tried to solve it with C++17. Here is my solution.
template<typename Derived>
constexpr bool is_eigen_type_f(const EigenBase<Derived> *) {
return true;
}
constexpr bool is_eigen_type_f(const void *) {
return false;
}
template<typename T>
constexpr bool is_eigen_type = is_eigen_type_f(reinterpret_cast<T *>(NULL));
#Jarod42
Thank you, your suggestion has brought some light but I found another option which I think will be pretty solid: I found an implementation of is_scalar<Type> in the namespace std::__1. Now my code reads
template < class Type, bool _is_scalar = std::__1::is_scalar<Type>::value > struct is_scalar;
template < class Type >
struct is_scalar<Type, true> : true_type {
using Scalar = Type;
};
template < class Type >
struct is_scalar<Type, false> : false_type {
using Scalar = typename Type::Scalar;
};
and I am correctly able to distinguish built-in and Eigen types! Thank you anyway!
Edit:
By looking at the source code of std::__1::is_scalar I also note that this solution might stand for any kind of container object as long as it provides a type Scalar which is
an arithmetic type OR
a member pointer OR
a pointer OR
a null pointer OR
an enumeration constant
Am I correct?
Related
I've been meaning to implement total ordering via SFINAE and the Curiously Recurring Template Pattern idiom for a while now. The general idea is as follows:
Define templates that check for relational operators (<, >, etc.)
Define base classes that define total ordering operators.
Define a base class from operator detection.
Inherit from base class.
For simplicity, I have ignored the == and != operators in this example.
Relational Operator Detection
I first define classes to statically check whether the class defines a specific feature. For example, here I detect the presence of the less-than operator, or operator<.
template <typename T>
class has_less
{
protected:
template <typename C> static char &test(decltype(std::declval<C>() < std::declval<C>()));
template <typename C> static long &test(...);
public:
enum {
value = sizeof(test<T>(0)) == sizeof(char)
};
};
template <typename T>
constexpr bool has_less_v = has_less<T>::value;
Total Ordering
I then define classes that implement total ordering from a given operator, for example, to define total ordering from the less-than operator, I would use the following:
template <typename T>
struct less_than_total
{
bool operator>(const T &t) { return t < static_cast<T&>(*this); }
bool operator>=(const T &t) { return !(static_cast<T&>(*this) < t); }
bool operator<=(const T &t) { return !(t < static_cast<T&>(*this)); }
};
Base Class
I then define a single base class that creates a typedef to implement the remaining operators by detecting the implemented operator.
template <bool B, typename T, typename F>
using conditional_t = typename std::conditional<B, T, F>::type;
template <typename T>
using total_ordering = conditional_t< // has_less
has_less_v<T>,
less_than_total<T>,
conditional_t< // has_less_equal
has_less_equal_v<T>,
less_equal_total<T>,
conditional_t< // has_greater
has_greater_v<T>,
greater_total<T>,
conditional_t< // has_greater_equal
has_greater_equal_v<T>,
greater_equal_total<T>,
symmetric<T> // symmetry
> // has_greater_equal
> // has_greater
> // has_less_equal
>; // has_less
Inheritance
All of these steps, individually, work. However, when I actually inherit from the base class using the curiously recurring pattern, the resulting class implements only one of these operators and the detection algorithms fail.
Example
I've boiled down the issue to a minimal example consisting of the core parts: operator detection (has_less, has_greater), total ordering implementation (total), a simplified base class (total), and a simple struct using these relational operators (A).
#include <type_traits>
// DETECTION
template <typename T>
class has_less
{
protected:
template <typename C> static char &test(decltype(std::declval<C>() < std::declval<C>()));
template <typename C> static long &test(...);
public:
enum {
value = sizeof(test<T>(0)) == sizeof(char)
};
};
template <typename T>
class has_greater
{
protected:
template <typename C> static char &test(decltype(std::declval<C>() > std::declval<C>()));
template <typename C> static long &test(...);
public:
enum {
value = sizeof(test<T>(0)) == sizeof(char)
};
};
// TOTAL ORDERING
template <typename T>
struct less_than_total
{
bool operator>(const T &t) { return t < static_cast<T&>(*this); }
bool operator>=(const T &t) { return !(static_cast<T&>(*this) < t); }
bool operator<=(const T &t) { return !(t < static_cast<T&>(*this)); }
};
template <typename T>
struct symmetry
{};
template <bool B, typename T, typename F>
using conditional_t = typename std::conditional<B, T, F>::type;
template <typename T>
struct total: conditional_t<
has_less<T>::value,
less_than_total<T>,
symmetry<T>
>
{};
// TEST
struct A: total<A>
{
bool operator<(const A &r)
{
return true;
}
};
int main(void)
{
static_assert(has_less<A>::value, "");
static_assert(has_greater<A>::value, "");
return 0;
}
Ideally, this example would compile, however, I get:
$ clang++ a.cpp -o a -std=c++14
a.cpp:79:5: error: static_assert failed ""
static_assert(has_less<A>::value, "");
^ ~~~~~~~~~~~~~~~~~~
a.cpp:80:5: error: static_assert failed ""
static_assert(has_greater<A>::value, "");
Unfortunately, the base class is not detecting the operators during inheritance, and SFINAE does not detect the less than or greater than operators in the resulting class.
Question and Follow-Up
I would like to know why this fails, since I have been doing member-function detection and member-type detection for a long time with the curiously recurring pattern without problem. And assuming there is no direct issue with my code, are there any work-arounds to implement total ordering in such a manner?
Edit
I'm able to achieve a subset of what I want using std::enable_if. In this case, the only simple answer is to implement everything in terms of operator< and then implement total ordering from that operator.
template <typename T>
struct total
{
template <typename U = T>
typename std::enable_if<has_less<U>::value, bool>::type
bool operator>(const T &l, const T &r) { return r < t; }
};
If would still like an answer for why my operator detection via SFINAE fails during inheritance, but succeeds for inherited methods.
The main problem with this is that A is an incomplete type when has_less<A> is instantiated (during the instantiation of total<A> as A's base class) -- at this point, the compiler doesn't yet know that A has an operator <.
So, has_less<A> is instantiated with its value == 0, and symmetry<A> is selected for total<A>'s base class -- so A never gets any of its additional operators.
After all this is decided, the compiler sees the definition of A::operator <, which it adds to A. After this, A is complete.
So we know why static_assert(has_greater<A>::value, ""); fails, but shouldn't we expect static_assert(has_less<A>::value, ""); to succeed? After all, now A has a less-than operator. The thing is, has_less<A> was already instantiated with the incomplete A, with value == 0 -- even though A has changed, there is no mechanism for updating previously instantiated compile-time values. So this assertion fails too, even though it looks like it should succeed.
To show that this is the case, make a copy of has_less, name it has_less2, and change the static assertion to static_assert(has_less2<A>::value, "");. Because has_less2<A> is instantiated after A gets its less-than operator, this assertion succeeds.
One way you can make the code succeed is to forward-declare A and declare a global operator <, for comparing two A objects, so that the compiler knows about this operator before A's base class is worked out. Something like this:
struct A;
bool operator < (const A &lh, const A& rh);
struct A : total<A> {
friend bool operator < (const A &lh, const A& rh) {
return true;
}
};
I understand that this is not really what you want, however -- it would be much nicer if the CRTP setup happened automatically, without any special accommodation required in the derived class. But this might still give you some insight which can help lead you to a proper solution. I will also think about this some more, and if I come up with anything, I'll update this answer.
One more thing: Comparison member functions should be const qualified. Like
bool operator>(const T &t) const { ...
This is really important and will prevent a lot of non-obvious problems compiling code which uses these classes later on.
Traits classes can be defined to check if a C++ class has a member variable, function or a type (see here).
Curiously, the ConceptTraits do not include traits to check if a C++ class defines a default constructor or given constructor?
Can traits be used to check the constructor presence?
If yes, how?
If not, why it is not possible?
Sorry for answering may own question.
Googling I have found that the actual reason we can not check if a class has constructor or a destructors is that, the known technique used to detect if a class has a member is based on taking the address of the member. But constructors and destructors have no name, we can not take the address of them.
If we can not take the address, I don't see a way to make the compiler react to a construction without instantiating it directly, but in this case there is no detection at compile time but an error.
So to answer my own question, I would say that with the current techniques it is not possible to detect them and compiler support is needed. But C++ has revealed a lot of surprises, and things that were not possible at a given time, were revealed are possible using another technique.
I hope a C++ language expert is reading that and can give a more clear explanation.
Concept Traits is no more maintained, but become part of Type Traits. And in docs of has_trivial_constructor and has_trivial_destructor, Boost authors explain clearly that compiler support is required to make this work.
A modification of Potatoswatter's answer
Works on gcc-4.6
#include <type_traits>
template< class T >
struct identity {
typedef T type;
};
template<bool, typename T, typename F>
struct if_c : identity<F> {};
template< typename T, typename F>
struct if_c<true,T,F> : identity<T> {};
template<typename Bool, typename T, typename F>
struct if_ : if_c< Bool::value, T, F> {};
template< class T >
struct is_default_constructible_;
template< class T >
struct is_default_constructible :
if_< std::is_arithmetic<T>,
std::true_type,
is_default_constructible_<T> >::type { };
template< class T >
struct is_default_constructible_ {
template<class D> class Acessible : public D
{
friend class is_default_constructible_<D>;
public:
//using D::D; may be needed once N2540 is implemented
};
template<int x>
class receive_size{};
template< class U >
static int sfinae( receive_size< sizeof Acessible<U>() > * );
template< class U >
static char sfinae( ... );
public:
enum { value = sizeof( sfinae<T>(0) ) == sizeof(int) };
};
struct p { p(); };
class q { q(); };
class r { r(int); };
#include <iostream>
using namespace std;
int main() {
cerr << is_default_constructible<int>::value << endl // outputs 1
<< is_default_constructible<p>::value << endl
<< is_default_constructible<q>::value << endl
<< is_default_constructible<r>::value << endl; // outputs 0
}
# g++-mp-4.6 --std=c++0x -Wall test.cpp && ./a.out
1
1
0
0
Warning: some analysis below is obsolete as of C++11. In C++11, access checking is done prior to instantiation and access violation is-not-an-error. Therefore the attached code may be more compliant. I haven't re-analyzed it.
I'm pretty new to SFINAE. Today it occurred to me to put a test expression inside a sizeof inside a template parameter in a function argument type.
According to N2634 this is not wrong, but highly unportable. (EDIT: appears to be compliant to C++0x FCD.) It can only return positive or fail to compile in GCC 4.2; GCC 4.5 scores a 3 out of 3 for my test cases.
The SFINAE rules were broadened (in this case) since C++03 in the FCD. New §14.8.2/8 (emphasis mine):
If a substitution results in an invalid type or expression, type deduction fails. An invalid type or expression is one that would be ill-formed if written using the substituted arguments. Access checking is not done as part of the substitution process. Consequently, when deduction succeeds, an access error could still result when the function is instantiated. Only invalid types and expressions in the immediate context of the function type and its template parameter types can result in a deduction failure. [ Note: The evaluation of the substituted types and expressions can result in side effects such as the instantiation of class template specializations and/or function template specializations, the generation of implicitly-defined functions, etc. Such side effects are not in the “immediate context” and can result in the program being ill-formed.
template< class T >
class is_default_constructible {
template<int x>
class receive_size{};
template< class U >
static int sfinae( receive_size< sizeof U() > * );
template< class U >
static char sfinae( ... );
public:
enum { value = sizeof( sfinae<T>(0) ) == sizeof(int) };
};
class q { q(); };
class r { r(int); };
#include <iostream>
using namespace std;
int main() {
cerr << is_default_constructible<int>::value << endl // outputs 1
// fails to compile: access violation
// FCD demands that access violations be unrecoverable
// indeed, it's murky: q is default-constructible, but only "rarely"
//<< is_default_constructible<q>::value << endl
<< is_default_constructible<r>::value << endl; // outputs 0
}
by using std::is_default_constructible, std::is_trivially_default_constructible, std::is_nothrow_default_constructible type traits you can not only check if a type has a default constructor but you can check for the properties of it. like if it's a trivial constructor.
MSDN says that the header defines has_default_constructor and such traits.
http://msdn.microsoft.com/en-us/library/bb982179.aspx
You may want to check this code example taken from libstdc++ in Gcc 4.6.1 and which I slightly modified to work with MSVC 2010 :
/!\ : is_default_constructible returns true even if the default constructor is private or protected, i still can't find a way to solve this, any idea ?) :
namespace std {
namespace detail {
template<typename _B1, typename _B2>
struct __and_
: public conditional<_B1::value, _B2, _B1>::type
{ };
template<typename _Pp>
struct __not_
: public integral_constant<bool, !_Pp::value>
{ };
template<typename _Tp>
struct __is_array_known_bounds
: public integral_constant<bool, (extent<_Tp>::value > 0)>
{ };
template<typename _Tp>
struct __is_array_unknown_bounds
: public __and_<is_array<_Tp>, __not_<extent<_Tp>>>::type
{ };
struct __do_is_default_constructible_impl
{
template<typename _Tp>
static true_type __test(int,decltype(_Tp())* a = 0);
template<typename>
static false_type __test(...);
};
template<typename _Tp>
struct __is_default_constructible_impl
: public __do_is_default_constructible_impl
{
typedef decltype(__test<_Tp>(0)) type;
};
template<typename _Tp>
struct __is_default_constructible_atom
: public __and_<__not_<is_void<_Tp>>,
__is_default_constructible_impl<_Tp>>::type
{ };
template<typename _Tp, bool = is_array<_Tp>::value>
struct __is_default_constructible_safe;
// The following technique is a workaround for a current core language
// restriction, which does not allow for array types to occur in
// functional casts of the form T(). Complete arrays can be default-
// constructed, if the element type is default-constructible, but
// arrays with unknown bounds are not.
template<typename _Tp>
struct __is_default_constructible_safe<_Tp, true>
: public __and_<__is_array_known_bounds<_Tp>,
__is_default_constructible_atom<typename
remove_all_extents<_Tp>::type>>::type
{ };
template<typename _Tp>
struct __is_default_constructible_safe<_Tp, false>
: public __is_default_constructible_atom<_Tp>::type
{ };
} // namespace detail
/// is_default_constructible
template<typename _Tp>
struct is_default_constructible
: public integral_constant<bool, (detail::__is_default_constructible_safe<
_Tp>::value)>
{ };
}
use :
class DefaultConstructible
{
public:
DefaultConstructible() {}
};
class NotDefaultConstructible
{
public:
NotDefaultConstructible(int i) {}
};
std::is_default_constructible<DefaultConstructible>::value // -> true
std::is_default_constructible<NotDefaultConstructible>::value // -> false
After shedding much blood, sweat, and tears, I finally found a way that works on every compiler I tried:
template<class T = void> struct is_default_constructible;
template<> struct is_default_constructible<void>
{
protected:
// Put base typedefs here to avoid pollution
struct twoc { char a, b; };
template<bool> struct test { typedef char type; };
public:
static bool const value = false;
};
template<> struct is_default_constructible<>::test<true> { typedef twoc type; };
template<class T> struct is_default_constructible : is_default_constructible<>
{
private:
template<class U> static typename test<!!sizeof(::new U())>::type sfinae(U*);
template<class U> static char sfinae(...);
public:
static bool const value = sizeof(sfinae<T>(0)) > 1;
};
I have a class template that intends to use its parameter K as the key to a map.
Is there any way to restrict the template parameter to be a type that complies with the Key in std::map?
I realize that even without such constraint, the compiler would spit out a pile of template errors like K having no operator < (), but it would be nice if I can make my code more obvious in specifying requirements.
C++11 solutions are welcome.
template< typename K >
class Foo
{
// lots of other code here...
private:
std::map< K, size_t > m_map;
};
It depends on what you mean by "complies." If you want to verify that K has a < operator then you might try the Boost Concept Checking Library.
#include "boost/concept_check.hpp"
template< typename K >
class Foo
{
BOOST_CONCEPT_ASSERT((boost::LessThanComparable< K >));
// lots of other code here...
private:
std::map< K, size_t > m_map;
};
However if you want to verify that < defines a StrictWeakOrdering on K, that would require testing run-time behaviour under all possible inputs.
C++11 version:
#include <type_traits>
template<class T>
struct satisfies_key_req{
struct nat{};
template<class K> static auto test(K* k) -> decltype(*k < *k);
template<class K> static nat test(...);
static bool const value = !std::is_same<decltype(test<T>(0)), nat>::value;
};
#include <iostream>
struct foo{};
int main(){
static bool const b = satisfies_key_req<int>::value;
std::cout << b << '\n';
static bool const b2 = satisfies_key_req<foo>::value;
std::cout << b2 << '\n';
}
Output:
1
0
The key point I used here is expression SFINAE: auto test(K* k) -> decltype(*k < *k). If the expression in the trailing-return-type is not valid, then this particular overload of test is removed from the overload set. In other words, it's SFINAE'd.
§14.8.2 [temp.deduct]
p6 At certain points in the template argument deduction process it is necessary to take a function type that makes use of template parameters and replace those template parameters with the corresponding template arguments. This is done at the beginning of template argument deduction when any explicitly specified template arguments are substituted into the function type, and again at the end of template argument deduction when any template arguments that were deduced or obtained from default arguments are substituted.
p7 The substitution occurs in all types and expressions that are used in the function type and in template parameter declarations. The expressions include not only constant expressions such as those that appear in array bounds or as nontype template arguments but also general expressions (i.e., non-constant expressions) inside sizeof, decltype, and other contexts that allow non-constant expressions.
p8 If a substitution results in an invalid type or expression, type deduction fails. An invalid type or expression is one that would be ill-formed if written using the substituted arguments. [...]
You can use it in three flavors for your Foo class to trigger an error.
// static_assert, arguably the best choice
template< typename K >
class Foo
{
static_assert<satisfies_key_req<K>::value, "K does not satisfy key requirements");
// lots of other code here...
private:
std::map< K, size_t > m_map;
};
// new-style SFINAE'd, maybe not really clear
template<
typename K,
typename = typename std::enable_if<
satisfies_key_req<K>::value
>::type
>
class Foo
{
// lots of other code here...
private:
std::map< K, size_t > m_map;
};
// partial specialization, clarity similar to SFINAE approach
template<
typename K,
bool = satisfies_key_req<K>::value
>
class Foo
{
// lots of other code here...
private:
std::map< K, size_t > m_map;
};
template<typename K>
class Foo<K, false>;
A complete solution to your problem probably is impossible. But I can suggest you a solution, if you want to restrict K to be a specific type you can define your class as follows
template <class K, bool = std::is_same<K,int>::value>
class Foo { ... };
template <class K>
class Foo<K,false> { Foo(); };
So if K is int your class works as expected. Otherwise you can not costruct object of type Foo<K>. Obviously you can refine the condition.
To check if K has the operator< you can use boost::has_less, but as you can check in the documentation this traits doesn't work properly always.
From your question, I guess you want one suitable error instead of loads of errors.
Following code finds, if a type has a valid operator < or not:
namespace OperatorExist
{
typedef char no[3]; // '3' can be any awkward number
template<typename T> no& operator < (const T&, const T&);
template<typename T>
struct LessThan {
static const bool value = (sizeof(*(T*)(0) < *(T*)(0)) != sizeof(no));
};
}
Now, you can specialize class Foo using the above construct:
template<typename K, bool = OperatorExist::LessThan<K>::value>
class Foo
{
// lots of other code here...
private:
std::map<K, size_t> m_map;
};
template<typename K>
class Foo<K, false>; // unimplemented for types not suitable for 'std::map'
As soon as you use some type A which doesn't have compatibility with std::map, the compiler will complain with single error:
error: aggregate ‘Foo<A> oa’ has incomplete type and cannot be defined
Demo
I am trying to create a base class that is a wrapper around std::array that overloads a bunch of common arithmetic operators. The end result will be sort of like std::valarray, but with static size. I'm doing this because I am creating a whole host of child classes for my library that end up replicating this functionality. For example, I need to create a MyPixel class and a MyPoint class, both of which are essentially just statically sized arrays that I can perform arithmetic on.
My solution is to create a StaticValArray base class from which MyPoint and MyPixel can derive. However to disallow users from adding a MyPoint to a MyPixel, I'm using the CRTP pattern as such:
template<class T1, class T2>
struct promote
{
typedef T1 type; // Assume there is a useful type promotion mechanism here
};
template<class T, size_t S, template<typename... A> class ChildClass>
class StaticValArray : public std::array<T,S>
{
public:
// Assume there are some conversion, etc. constructors here...
template<class U>
StaticValArray<typename promote<T,U>::type,S,ChildClass> operator+
(StaticValArray<U,S,ChildClass> const & rhs)
{
StaticValArray<typename promote<T,U>::type,S,ChildClass> ret = *this;
std::transform(this->begin(), this->end(),
rhs.begin(), ret.begin(), std::plus<typename promote<T,U>::type>());
return ret;
}
// More operators....
};
This is pretty cool, because the ChildClass can have any arbitrary class template parameters, and this thing will work. For example:
template<class T, class U>
class MyClassTwoTypes : public StaticValArray<T,3,MyClassTwoTypes>
{ };
template<class T, class U>
class MyClassTwoTypes2 : public StaticValArray<T,3,MyClassTwoTypes2>
{ };
int main()
{
MyClassTwoTypes<int, float> p;
MyClassTwoTypes<double, char> q;
auto z = p + q;
MyClassTwoTypes2<double, char> r;
// r += q; // <-- Great! This correctly won't compile
return 0;
}
My problem is this: I would like to stuff some ChildClass into the CRTP bit of StaticValArray that doesn't necessarily have just classes as its template parameters. For example, consider this N-Dimensional Point class:
template<class T, size_t S>
class MyPointND : public StaticValArray<T,S,MyPointND>
{ };
This unfortunately won't compile, because size_t is not a typename - I get the compiler error:
type/value mismatch at argument 3 in template parameter list for ‘template<class T, long unsigned int S, template<class ... A> class ChildClass> class StaticValArray’
test.C:36:54: error: expected a template of type ‘template<class ... A> class ChildClass’, got ‘template<class T, long unsigned int S> class MyPointND’
Is there any way to create a variadic template template parameter pack that can be absolutely anything (typenames, ints, size_t's, doubles, whatever?) because in the end I really don't care what the type is in there. Note that I can't just fully specify ChildClass (e.g. class MyPointND: public StaticValArray<T,S,MyPointND<T,S>>) because this would break my type promotion mechanism.
What if, in place of the size_t, you used an std::integral_constant? You would embed the numerical value of the size of your array in it, and you could use it as a type.
EDIT
In order to reduce the verbosity, you could define your own integral constant class, something like:
template <std::size_t N>
struct size_ : std::integral_constant<std::size_t,N> {};
Then you could use it like this:
MyPointND<int,size_<3>> x;
What you need to do is have a traits class, specialized for each type containing whatever you need for type promotion, and then pass in the complete type to the StaticValArray.
Moreover, with decltype, you shouldn't need anything like this- decltype will tell you what you get by adding a float and an int.
template<class U>
StaticValArray<decltype(*(T*)nullptr + *(U*)nullptr),S,ChildClass> operator+
(StaticValArray<U,S,ChildClass> const & rhs)
{
StaticValArray<decltype(*(T*)nullptr + *(U*)nullptr),S,ChildClass> ret = *this;
std::transform(this->begin(), this->end(),
rhs.begin(), ret.begin(), std::plus<decltype(*(T*)nullptr + *(U*)nullptr)>());
return ret;
}
Traits classes can be defined to check if a C++ class has a member variable, function or a type (see here).
Curiously, the ConceptTraits do not include traits to check if a C++ class defines a default constructor or given constructor?
Can traits be used to check the constructor presence?
If yes, how?
If not, why it is not possible?
Sorry for answering may own question.
Googling I have found that the actual reason we can not check if a class has constructor or a destructors is that, the known technique used to detect if a class has a member is based on taking the address of the member. But constructors and destructors have no name, we can not take the address of them.
If we can not take the address, I don't see a way to make the compiler react to a construction without instantiating it directly, but in this case there is no detection at compile time but an error.
So to answer my own question, I would say that with the current techniques it is not possible to detect them and compiler support is needed. But C++ has revealed a lot of surprises, and things that were not possible at a given time, were revealed are possible using another technique.
I hope a C++ language expert is reading that and can give a more clear explanation.
Concept Traits is no more maintained, but become part of Type Traits. And in docs of has_trivial_constructor and has_trivial_destructor, Boost authors explain clearly that compiler support is required to make this work.
A modification of Potatoswatter's answer
Works on gcc-4.6
#include <type_traits>
template< class T >
struct identity {
typedef T type;
};
template<bool, typename T, typename F>
struct if_c : identity<F> {};
template< typename T, typename F>
struct if_c<true,T,F> : identity<T> {};
template<typename Bool, typename T, typename F>
struct if_ : if_c< Bool::value, T, F> {};
template< class T >
struct is_default_constructible_;
template< class T >
struct is_default_constructible :
if_< std::is_arithmetic<T>,
std::true_type,
is_default_constructible_<T> >::type { };
template< class T >
struct is_default_constructible_ {
template<class D> class Acessible : public D
{
friend class is_default_constructible_<D>;
public:
//using D::D; may be needed once N2540 is implemented
};
template<int x>
class receive_size{};
template< class U >
static int sfinae( receive_size< sizeof Acessible<U>() > * );
template< class U >
static char sfinae( ... );
public:
enum { value = sizeof( sfinae<T>(0) ) == sizeof(int) };
};
struct p { p(); };
class q { q(); };
class r { r(int); };
#include <iostream>
using namespace std;
int main() {
cerr << is_default_constructible<int>::value << endl // outputs 1
<< is_default_constructible<p>::value << endl
<< is_default_constructible<q>::value << endl
<< is_default_constructible<r>::value << endl; // outputs 0
}
# g++-mp-4.6 --std=c++0x -Wall test.cpp && ./a.out
1
1
0
0
Warning: some analysis below is obsolete as of C++11. In C++11, access checking is done prior to instantiation and access violation is-not-an-error. Therefore the attached code may be more compliant. I haven't re-analyzed it.
I'm pretty new to SFINAE. Today it occurred to me to put a test expression inside a sizeof inside a template parameter in a function argument type.
According to N2634 this is not wrong, but highly unportable. (EDIT: appears to be compliant to C++0x FCD.) It can only return positive or fail to compile in GCC 4.2; GCC 4.5 scores a 3 out of 3 for my test cases.
The SFINAE rules were broadened (in this case) since C++03 in the FCD. New §14.8.2/8 (emphasis mine):
If a substitution results in an invalid type or expression, type deduction fails. An invalid type or expression is one that would be ill-formed if written using the substituted arguments. Access checking is not done as part of the substitution process. Consequently, when deduction succeeds, an access error could still result when the function is instantiated. Only invalid types and expressions in the immediate context of the function type and its template parameter types can result in a deduction failure. [ Note: The evaluation of the substituted types and expressions can result in side effects such as the instantiation of class template specializations and/or function template specializations, the generation of implicitly-defined functions, etc. Such side effects are not in the “immediate context” and can result in the program being ill-formed.
template< class T >
class is_default_constructible {
template<int x>
class receive_size{};
template< class U >
static int sfinae( receive_size< sizeof U() > * );
template< class U >
static char sfinae( ... );
public:
enum { value = sizeof( sfinae<T>(0) ) == sizeof(int) };
};
class q { q(); };
class r { r(int); };
#include <iostream>
using namespace std;
int main() {
cerr << is_default_constructible<int>::value << endl // outputs 1
// fails to compile: access violation
// FCD demands that access violations be unrecoverable
// indeed, it's murky: q is default-constructible, but only "rarely"
//<< is_default_constructible<q>::value << endl
<< is_default_constructible<r>::value << endl; // outputs 0
}
by using std::is_default_constructible, std::is_trivially_default_constructible, std::is_nothrow_default_constructible type traits you can not only check if a type has a default constructor but you can check for the properties of it. like if it's a trivial constructor.
MSDN says that the header defines has_default_constructor and such traits.
http://msdn.microsoft.com/en-us/library/bb982179.aspx
You may want to check this code example taken from libstdc++ in Gcc 4.6.1 and which I slightly modified to work with MSVC 2010 :
/!\ : is_default_constructible returns true even if the default constructor is private or protected, i still can't find a way to solve this, any idea ?) :
namespace std {
namespace detail {
template<typename _B1, typename _B2>
struct __and_
: public conditional<_B1::value, _B2, _B1>::type
{ };
template<typename _Pp>
struct __not_
: public integral_constant<bool, !_Pp::value>
{ };
template<typename _Tp>
struct __is_array_known_bounds
: public integral_constant<bool, (extent<_Tp>::value > 0)>
{ };
template<typename _Tp>
struct __is_array_unknown_bounds
: public __and_<is_array<_Tp>, __not_<extent<_Tp>>>::type
{ };
struct __do_is_default_constructible_impl
{
template<typename _Tp>
static true_type __test(int,decltype(_Tp())* a = 0);
template<typename>
static false_type __test(...);
};
template<typename _Tp>
struct __is_default_constructible_impl
: public __do_is_default_constructible_impl
{
typedef decltype(__test<_Tp>(0)) type;
};
template<typename _Tp>
struct __is_default_constructible_atom
: public __and_<__not_<is_void<_Tp>>,
__is_default_constructible_impl<_Tp>>::type
{ };
template<typename _Tp, bool = is_array<_Tp>::value>
struct __is_default_constructible_safe;
// The following technique is a workaround for a current core language
// restriction, which does not allow for array types to occur in
// functional casts of the form T(). Complete arrays can be default-
// constructed, if the element type is default-constructible, but
// arrays with unknown bounds are not.
template<typename _Tp>
struct __is_default_constructible_safe<_Tp, true>
: public __and_<__is_array_known_bounds<_Tp>,
__is_default_constructible_atom<typename
remove_all_extents<_Tp>::type>>::type
{ };
template<typename _Tp>
struct __is_default_constructible_safe<_Tp, false>
: public __is_default_constructible_atom<_Tp>::type
{ };
} // namespace detail
/// is_default_constructible
template<typename _Tp>
struct is_default_constructible
: public integral_constant<bool, (detail::__is_default_constructible_safe<
_Tp>::value)>
{ };
}
use :
class DefaultConstructible
{
public:
DefaultConstructible() {}
};
class NotDefaultConstructible
{
public:
NotDefaultConstructible(int i) {}
};
std::is_default_constructible<DefaultConstructible>::value // -> true
std::is_default_constructible<NotDefaultConstructible>::value // -> false
After shedding much blood, sweat, and tears, I finally found a way that works on every compiler I tried:
template<class T = void> struct is_default_constructible;
template<> struct is_default_constructible<void>
{
protected:
// Put base typedefs here to avoid pollution
struct twoc { char a, b; };
template<bool> struct test { typedef char type; };
public:
static bool const value = false;
};
template<> struct is_default_constructible<>::test<true> { typedef twoc type; };
template<class T> struct is_default_constructible : is_default_constructible<>
{
private:
template<class U> static typename test<!!sizeof(::new U())>::type sfinae(U*);
template<class U> static char sfinae(...);
public:
static bool const value = sizeof(sfinae<T>(0)) > 1;
};