Variadic templates - incomplete type - c++

Having this code:
template<class ...Args>
struct Are_Same
{
enum {value = Are_Same<Args...>::value};
};
template<class A,class... C>
struct Are_Same<A,C...>
{
enum {value = Are_Same<A,C...>::value};//HERE is THE ERROREOUS LINE
};
template<class A,class B>
struct Are_Same<A,B>
{
enum {value = std::is_same<A,B>::value};
};
I'm getting error from gcc 4.6.1:
error: incomplete type 'Are_Same' used in
nested name specifier.
I thought that by doing Are_Same<A,C...>::value I will invoke recursive call which at the end will simply expand to Are_Same<A,B>. Obviously it's not the case. Anyone knows where am I making mistake?

I think that the definitions of the templates are wrong, in both cases you are triggering exact recursion. I would have expected the compiler to die with some stackoverflow inside the compiler but a different error is produced...
An implementation of the are_same variadic template could be:
template <class... Args> // base (optional to declare the template)
struct are_same;
template <class A, class B, class... Args> // recursion
struct are_same<A,B,Args...> {
static const bool value = is_same<A,B>::value && are_same<A,Args...>::value;
};
template <class A, class B> // stop condition
struct are_same<A,B> {
static const bool value = is_same<A,B>::value;
};
Note that in the recursion step, one argument is dropped from the list of arguments, so that the new problem to resolve is a reduced version of the original. This type of template metaprogramming is quite related to recursion, and the same rules apply, to be able to use recursion you need to ensure that each recursive step gets you closer to a solution. In this particular case, given a list of N potentially same types, each step reduces the problem to finding whether N-1 types are the same.
You can use alternatively, as stop condition (replacing the former one) a degenerate version of the are_same problem:
template <class A>
struct are_same<A> {
static const bool value = true;
};
Which is degenerate in the sense that it does not really make sense asking whether a single type *are_same*, but for different metaprogramming tasks it could be appropriate.
A different potentially more efficient algorithm (I am not sure whether the compiler will avoid the instantiation of the template in the recursion step above) that does not depend on is_same could be:
template <class... Args>
struct are_same;
template <class A, class... Args>
struct are_same<A,A,Args...> { // recursion
static const bool value = are_same<A,Args...>::value;
};
template <class A, class B, class... Args>
struct are_same<A,B,Args...> { // cut, A and B are not the same
static const bool value = false;
};
template <class A>
struct are_same<A> { // end of recursion
static const bool value = true;
};
In this case, the compiler will prefer the recursion to the cut steps whenever the two types are the same, so we need not check is_same internally. At the same time, if the compiler goes into the cut step, we don't need to process the rest of the type list, as we already know the answer.

I would do it like this :
#include <type_traits>
#include <iostream>
template <class... Args>
struct are_same
{
static const bool value=true;
};
template <class A, class B, class... Args> // recursion
struct are_same<A,B,Args...> {
static const bool value = std::is_same<A,B>::value && are_same<B,Args...>::value;
};
int main()
{
std::cout<< std::boolalpha << are_same< int >::value << std::endl;
std::cout<< std::boolalpha << are_same< int, int, int >::value << std::endl;
std::cout<< std::boolalpha << are_same< int, int, double, int >::value << std::endl;
}

Probably simplest implementation could be like this:
template <typename... TList>
struct are_same { constexpr static bool value = false; };
template <typename T, typename... TList>
struct are_same<T, T, TList...> {
constexpr static bool value = are_same<T, TList...>::value;
};
template <typename T>
struct are_same<T> { constexpr static bool value = true; };
Alternatively you can replace stop condition with
template <typename T>
struct are_same<T, T> { constexpr static bool value = true; };
But the first one is more general because are_same<type>::value == true. Another question is what should be are_same<>::value equal to. This gives you false but it is not a big deal to add one more template specialisation like this.
template <>
struct are_same<> { constexpr static bool value = true; };

Related

Using specialization to test the existence of a value within a class

Lets say I have the following class:
struct Color
{
enum {
blue,
red,
unknown
};
};
I would like to test in compile time if the class Color has the unknown value.
I thought the following could work but it is currently returning an incorrect result.
#include <iostream>
template <typename T, typename U = T>
struct test
{
static constexpr bool value = false;
};
template <typename T>
struct test<T, decltype(T::unknown)>
{
static constexpr bool value = true;
};
int main()
{
std::cout << test<Color>::value << std::endl; //prints 0
}
Could you provide some insight on how I can accomplish the check?
Or what is wrong with my example?
Thanks
When you write test<Color>, we first instantiate the primary specialization of test, which includes filling in the default template parameters. So we get test<Color, Color>.
Next, we try to see if any of the specializations match. The one specialization is for test<Color, Color::<unnamed>>. This doesn't match, so we stick with the primary!
This type mismatch is why void_t exists - so that our defaulted template parameter on the primary can match the specialization:
template <typename T, typename U = void>
// ~~~~~~~
struct test
{
static constexpr bool value = false;
};
template <typename T>
struct test<T, void_t<decltype(T::unknown)>>
// ~~~~~~~ ~
{
static constexpr bool value = true;
};
Also, prefer to just inherit from false_type and true_type, respectively.

Check the existence of a template function

How can I check the existence of a template function like this: Checking if reader struct has read arithmetic value
struct reader {
template<typename T>
std::enable_if_t<std::is_arithmetic<T>::value, T> read() {
return {};
}
};
I use a checker like this:
template <typename T>
struct test_read {
static constexpr auto value = std::is_convertible<decltype(std::declval<T>().read<int>()),int>::value;
};
But the compiler complains:
error: wrong number of template arguments (1, should be 2)
static constexpr auto value = std::is_convertible<decltype(std::declval<T>().read<int>()),int>::value;
Please give me your advice on that.
Thank you.
Update: Here is the final version I got after discussion, I hope everyone will find it helpful for your code
struct not_reader {
};
struct reader {
template<typename T>
std::enable_if_t<std::is_arithmetic<T>::value, T> read() {
return {};
}
};
template<class T, class Elem>
struct has_read {
private:
template<class C, typename=void>
struct test_read : std::false_type {
};
template<class C>
struct test_read<C, typename std::enable_if<std::is_convertible<decltype(std::declval<C>().template read<Elem>()), Elem>::value>::type>
: std::true_type {
};
public:
using type = typename test_read<T>::type;
static constexpr bool value = test_read<T>::value;
};
static_assert(has_read<reader, int>::value, "reader should have int read()");
static_assert(!has_read<not_reader, int>::value, "not_reader should not have int read()");
You forgot template before read()
static constexpr auto value
= std::is_convertible<
decltype(std::declval<T>().template read<int>()),int>::value;
// .................................#########
But I don't think that your code can check " if reader struct has read arithmetic value": try calling test_read with type int and you should get a compilation error.
The following is an example of an alternative solution
#include <type_traits>
struct reader
{
template<typename T>
std::enable_if_t<std::is_arithmetic<T>::value, T> read()
{ return {}; }
};
template <typename, typename = void>
struct readTypeRet
{ using type = void; };
template <typename T>
struct readTypeRet<T, decltype(std::declval<T>().template read<int>(), void())>
{ using type = decltype(std::declval<T>().template read<int>()); };
template <typename T>
struct test_read
: public std::is_convertible<typename readTypeRet<T>::type, int>
{ };
int main ()
{
static_assert(test_read<reader>::value == true, "!");
static_assert(test_read<int>::value == false, "!");
}
To briefly restate your problem in terms that are a bit clearer:
You have some function that will return T if T satisfies is_arithmetic, otherwise it returns void
You want to assert that calling this function with int will return a type convertible to int
I think the shortest path to fix your code is to take advantage of std::result_of (C++11/14, use std::invoke_result_t in C++17):
template<class T>
struct test_read {
static constexpr auto value = std::is_convertible<
typename std::result_of<decltype(&T::template read<int>)(T)>::type, int
>::value;
};
Live Demo
Some notes about this solution:
When specifying the read member function of T (reader), we need to use the template keyword to inform the compiler that the name reader is a template.
Use of result_of requires a function-like syntax of F(Args), so here we are getting the type of reader::read as the F portion, and then passing reader as the Args portion
we must pass an instance of T (reader) to read because it is a member function (rather than static or free), and member functions implicitly take a reference to the instance of the class they're being called on.

How to use SFINAE to make a polyfill for missing values in enum class?

I thought this should be easy, but I've been struggling with it for a while so I thought I should ask here.
I want to make a template metafunction that takes a type corresponding to a C++11 enum class as its argument, and returns an int:
If the enum class E has an enumerator value a, then return static_cast<int>(E::a).
If the enum class E does not have an enumerator value a, then return 42.
Then I would like to make a template function that takes a run-time instance of some enum class E, static casts it to int, and checks if it matches this metafunction.
I tried many iterations of, templating a struct and use template partial specialization to try to distinguish if E::a exists, also using function templates... I'm not sure if I can reconstruct everything that I tried but here's the most recent iteration:
template <typename E>
inline int get_a_int_val(int result = E::a) { return result; }
template <typename E>
inline int get_a_int_val(int result = 42) { return result; }
template <typename E>
inline bool is_a_val(const E & input) {
return static_cast<int>(input) == get_a_int_val<E>();
}
This doesn't work, because I'm redefining default arguments.
template <typename E, int result = E::a>
inline int get_a_int_val() { return result; }
template <typename E, int result = 42>
inline int get_a_int_val() { return result; }
template <typename E>
inline bool is_a_val(const E & input) {
return static_cast<int>(input) == get_a_int_val<E>();
}
This doesn't work, because non-type parameters cannot depend on type parameters.
template <typename E>
struct get_a_int_val {
static const int value = 42;
};
template <typename E>
struct get_a_int_val<E> {
static const int value = static_cast<int>(E::a);
};
template <typename E>
inline bool is_a_val(const E & input) {
return static_cast<int>(input) == get_a_int_val<E>::value;
}
This doesn't work, because
error:
class template partial specialization does not specialize any template
argument; to define the primary template, remove the template argument
list
What's the correct way to do this?
Motivation:
The reason that I want to do this is, I want to work around what seems to be a bug in libstdc++ which I reported here: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68307
In C++11 in the <system_error> header, there are a bunch of enumerator values for std::errc which are supposed to be defined, however, on mingw some of them are missing. This causes compilation errors in my program because, depending on how Asio is configured, lib::asio::errc may be typedef'd to std::errc, and websocketpp assumes that lib::asio::errc::operation_canceled is a defined symbol. I wanted to throw together some kind of shim that I can put around that in the websocketpp code so that it will be defined acceptably on any platform (either to lib::asio::errc::operation_canceled if it exists, or to ECANCELED from <cerrno> if not.)
You can do this in many ways, one of them is the following:
template <typename E, typename Enable = void>
struct get_a_int_val {
static const int value = 42;
};
template <typename E>
struct get_a_int_val<E, typename std::enable_if<std::is_same<decltype(E::a),
decltype(E::a)>::value, void>::type>{
static const int value = static_cast<int>(E::a);
};
LIVE DEMO
You may create a traits for that:
template <typename E>
std::false_type has_a_impl(...);
template <typename E> auto has_a_impl(int) -> decltype(E::a, std::true_type{});
template <typename E>
using has_a = decltype(has_a_impl<E>(0));
And then use it in SFINAE:
template <typename E>
std::enable_if_t<has_a<E>::value, int>
get_a_int_val() { return static_cast<int>(E::a); }
template <typename E>
std::enable_if_t<!has_a<E>::value, int>
get_a_int_val() { return 42; }
Demo

Basic Typelist functionality

I'm having a bit of trouble getting my head around TypeLists or lists of templates. That is:
class nulltype{};
template <typename HEAD, typename TAIL>
struct tlist
{
typedef HEAD head;
typedef TAIL tail;
};
template <class TList>
class OutputClass
{
public:
void output(Type t)
{
std::cout << t << endl;
}
};
typedef tlist<double,tlist<float,NullType> > floatingPoints;
typedef tlist<std::string,tlist<char *,NullType> > text;
int main()
{
OutputClass<floatingPoints> floats = OutputClass<floatingPoints>();
floats.output(1.0f);
OutputClass<text> strings = OutputClass<text>();
floats.output("hello");
return 0;
}
Basically my goal is that I would like OutputClass.output to output the parameter passed to it, but only if that class instances typelist contains the type passed into the function. ie. referring to the above code: floats can only output float type and double type as defined by its typelist, "floatingPoints". Should a string or int get passed in, I would hope it would error.
I'm having one hell of a time trying to find any examples on how to do this, I've found the indexing examples and length examples a million times over, and they have helped me a lot, but i just can't seem to figure this last bit out. Any and all help will be appreciated.
We first need some helper templates. The first one checks if two types are the same:
template <typename T, typename U>
struct is_same
{
// Default case: T and U are not the same type
static const bool value = false;
};
template <typename T>
struct is_same<T, T>
{
// Specialization: both template arguments are of the same type
static const bool value = true;
};
We can now use the boolean is_same<T, U>::value to determine if the types T and U are equivalent.
Using is_same we can now write a template which checks if a specific type occurs in a type list:
template <typename TList, typename T>
struct contains
{
static const bool value =
is_same<typename TList::head, T>::value // Base case
|| contains<typename TList::tail, T>::value; // Recursion
};
template <typename T>
struct contains<nulltype, T>
{
// Termination condition
static const bool value = false;
};
This is a recursive template, using a specialization on nulltype to terminate the recursion.
One final helper template we need is enable_if:
template <bool Cond, typename T=void>
struct enable_if
{
// Default case: Cond assumed to be false, no typedef
};
template <typename T>
struct enable_if<true, T>
{
// Specialization: Cond is true, so typedef
typedef T type;
};
enable_if<true, T>::type yields T, whereas enable_if<false, T>::type is undefined. We exploit the SFINAE rule the enable or disable a function depending on its template argument, like so:
template <typename TList>
class OutputClass
{
public:
// Only enable the function if T is in TList (by SFINAE)
template <typename T>
typename enable_if<contains<TList, T>::value>::type
output(T t)
{
std::cout << t << std::endl;
}
};
Quite a trip, but if you understand all of this you're well on your way to master template metaprogramming. For an in-depth discussion of template metaprogramming I recommend you pick up a copy of C++ Template Metaprogramming (ISBN-13: 9780321227256).

SFINAE approach comparison

The following code shows an SFINAE implementation to check whether a type (basically a class) contains a member function member_func at compile time.
#define CHECKER(func_name,class_name) sizeof(class_name<T>::template func_name<T>(0)) == 1
#include <iostream>
struct A
{
void member_func();
};
struct B {};
template<typename T>struct Check_If_T_Is_Class_Type
{
template<typename C> static char func (char C::*p);
template<typename C> static long func (...);
enum{val = CHECKER(func,Check_If_T_Is_Class_Type)};
};
//APPROACH 1
template <typename T>struct TypeHasMemberFunc
{
template <typename C, C> struct TypeCheck;
template <typename C> struct Prototype_Holder {typedef void (C::*fptr)();};
template <typename C> static char func(TypeCheck
<
typename Prototype_Holder<C>::fptr,
&C::member_func
>*);
template <typename C> static long func(...);
enum {value = CHECKER(func,TypeHasMemberFunc)};
};
//APPROACH 2
template <typename T>struct has_member_func
{
template<class C> static char func(char (*)[sizeof(&C::member_func)]);
template<class C> static long func(...);
enum{value = CHECKER(func,has_member_func)};
};
int main(){
if(Check_If_T_Is_Class_Type<A>::val)
std::cout<<TypeHasMemberFunc<A>::value; //using APPROACH 1
if(Check_If_T_Is_Class_Type<B>::val)
std::cout<<has_member_func<B>::value; //using APPROACH 2
}
However my question is which approach would you prefer (APPROACH 1 or APPROACH 2) and why?
Do you find any inconsistency in the given approaches? If yes please let me know.
P.S : Assume sizeof(char)!= sizeof(long)
Second approach doesn't check function type (return type or arguments types) and does work with all types, not only class types.
I would personally prefer the second approach to play with as it is shorter and easier to understand. But GCC won't compile it, so you have to use something like that for GCC:
namespace detail
{
template<class C> char func(char (*)[sizeof(&C::member_func)]);
template<class C> long func(...);
}
template <typename T>struct has_member_func
{
enum{value = (sizeof(detail::func<T>(0)) == 1)};
};
Also, It would be nice to get rid of CHECKER macro. It makes your code extremely less readable.
Anyway, I would refrain from using such C++ hacks in production code (except you are a Boost team member :-)
Such stuff is error-prone, hard to support, hardly portable between compilers but the principal point is that I do not remember any real life task demanded such hard-code C++.
EDIT: completed and corrected.
Another approach, using ambiguity from inheritance, probably functionally equivalent to your Approach 2. I remember having problems with Approach 1 (it compiles with G++ 4.4.5 though) because the name resolution triggered an error and not a substitution failure. I had to resort to:
template <class T>
struct has_foo
{
struct fallback { void foo(...); };
struct D : T, fallback { };
template <typename U, U> struct K;
// Will be ambiguous for U = D iff T has a foo member function.
// It doesn't trigger an error, since D will always have at least one
// foo member function.
template <class U> static char (&test(K<void (fallback::*)(...), &U::foo>*))[1];
template <class U> static char (&test(...))[2];
static const bool value = sizeof(test<D>(0)) == 2;
};
This works when T is a class, so you may want to add your layer for checking whether T is a class type.
Note that any foo member function will be detected. If you want to check whether the detected foo function can be called with given arguments, you have to do another layer of SFINAE:
// Check whether foo can be called with an argument of type Arg
// and yields an element of type Res.
// If you need Res = void, this code does not work.
template <class T, typename Arg, typename Res>
struct check_foo
{
struct flag {};
struct D : T { using T::foo; flag foo(...); };
template <typename U>
static char (&test(U))[1];
template <typename> static char (&test(...))[2];
static Arg f();
static const bool value = sizeof(test<Arg>( ((D*)0)->foo(f()) )) == 1;
};