Reputation: 1547
I'm trying to combine forward declarations in a template library, with type guards to intercept cases of the wrong type of template being used with the wrong type of class. Here is the simplest snippet of code I can get down to, in order to illustrate the problem...
Main.cpp
#include <iostream>
#include "templates.h"
int main()
{
B<int_array> hello;
return 0;
}
templates.h
#include <type_traits>
#define USE_GUARD
#define FORWARD_DECLARE
template<typename T>
using is_pod = typename std::enable_if<std::is_pod<T>::value>::type;
typedef struct {
int *p;
int n;
} int_array;
template <typename E, typename T >
class A
{
};
#ifdef USE_GUARD
template <typename T, typename = is_pod<typename std::remove_pointer<decltype(T::p)>::type> >
#else
template <typename T>
#endif
class B : public T, public A< B<T>, T >
{ // This is the 'curiously recurring template
// pattern' (CRTP)
public:
//! Default constructor
B() noexcept
{
T::p = nullptr;
T::n = 0;
}
#ifdef FORWARD_DECLARE
void reorder(const int_array & newOrder);
#endif
};
template <typename T> class C : public B<T>
{
public:
C() noexcept : B<T>()
{
T::p = nullptr;
T::n = 0;
}
};
#ifdef FORWARD_DECLARE
#ifdef USE_GUARD
template <typename T, typename = is_pod<typename std::remove_pointer<decltype(T::p)>::type> >
#else
template <typename T>
#endif
void B<T>::reorder(const int_array & newOrder)
{
C<T> myC;
}
#endif
I get error messages as follows:
Visual Studio 2015:
Neither USE_GUARD nor FORWARD_DECLARE defined - works fine
Only FORWARD_DECLARE defined - works fine
Only USE_GUARD defined - works fine
Both defined - C3860: template argument lost following class template name must list parameters in the order used in template parameter list
g++:
Neither USE_GUARD nor FORWARD_DECLARE defined - works fine
Only FORWARD_DECLARE defined - works fine
Only USE_GUARD defined - works fine
Both defined - Invalid use of incomplete type 'class B<T>
at the point where the function 'reorder' is defined
So there's obviously something that I'm doing wrong in the way that I combine the type guard with the forward declaration, but neither compiler is giving me a very intelligible error message. Am I making an elementary error in my syntax, or am I just trying to do something fundamentally silly?
Upvotes: 0
Views: 90
Reputation: 217810
Default argument should not be repeated in member definition, and all arguments should be provided:
#ifdef FORWARD_DECLARE
# ifdef USE_GUARD
template <typename T, typename U>
void B<T, U>::reorder(const int_array & newOrder)
# else
template <typename T>
void B<T>::reorder(const int_array & newOrder)
# endif
{
C<T> myC;
}
#endif
Upvotes: 1