Simplification of Template Class Specification - c++

I am very interested in the possibilities of template classes. Now, I am wondering how I can achieve following:
Const<5>::getValue();
At the moment I can do this:
Const<int, 5>::getValue());
And that's the implementation of the class:
template <typename T, T value>
class Const {
public:
typedef T Type;
static T getValue() {
return value;
}
};
I know this is just a very silly example, but once I can do that I could simplify following line:
Getter<int, TestClass, &TestClass::get> getter;
to just:
Getter<&TestClass::get> getter;
That would be TestClass :
class TestClass {
private:
int _value;
public:
int get() {
return _value;
}
};
Thanks for your help!
[EDIT-1]
In regards to J.N. yes, C++11 would be fine.
In regards to Xeo, I tried to use #define AUTO_ARG(x) decltype(x), x but that doesn't work within TestClass.
[EDIT-2]
In regards to KennyTM, when I declare the Getter<...> g within TestClass it doesn’t work with Getter<AUTO_ARG(&TestClass::get)> it only works with Getter<int (TestClass::*)() const, &TestClass::get>.
Now I am wondering if this is just a bug in Visual Studio???

You could still use AUTO_ARG(x) as given by #Xeo's link. If you need to get the return type or the class type, just use pattern matching (i.e. template specialization):
template <typename T, T mem_fun_ptr>
struct Getter;
template <typename R, typename C, typename... A, R (C::*mem_fun_ptr)(A...) const>
struct Getter<R (C::*)(A...) const, mem_fun_ptr>
{
typedef R return_type;
typedef C class_type;
};
#define AUTO_ARG(x) decltype(x),(x)
class TestClass {
private:
int _value;
public:
int get() const {
return _value;
}
};
Getter<AUTO_ARG(&TestClass::get)> g;

Related

Invalid use of incomplete type (chained templated classes)

I am trying to create a filesystem interface so that my micro controller can interface with an SD card (and I decided to implement all of the File System stuff from the ground up). The problem is I don't know what file system will be on the card....It could be FAT16, FAT32, NFTS, ext3, ect.
So I created a the following abstract classes: FileSystem File and Directory. Now that is all fine and dandy but I am on a micro controller so I want to avoid using the new operator.
This leads to my creation of the UnionBase class (not a very helpful name). Basically this class holds a union of all of the different derived classes and allows you to convert between them:
struct BaseFile_t{
};
struct DerivedA : BaseFile_t{
};
struct DerivedB : BaseFile_t{
};
UnionBase<BaseFile_t,DerivedA,DerivedB> var; //Can now pass references
//of this into File system function
//so that they can modify the right
//Derived type (which can then be
//used as if it is the base type)
Now in order to pass this in I have a struct called FileSystemUnion or FSU for short. This basically just defines all of the necessary BaseUnion types.
The real problem is that it seems that it might end up being a type if recursive typedef (which I know is not allowed). Here is a shortened version of my code:
#include <stdio.h>
#include <iostream>
#include <string>
#include <conio.h>
#include <stdlib.h>
#include <fstream>
#include "prototypeInd/templates/UnionBase.h"
using namespace prototypeInd::templates;
template<class arg,class conv>
struct File{
};
template<class arg,class conv>
struct Directory : public File<arg,conv>{
};
template<class arg,class conv>
struct FS{
typedef Directory<arg,conv> Directory;
typedef File<arg,conv> File;
};
template<class arg,class conv>
struct DFile : public virtual File<arg,conv>{
};
template<class arg,class conv>
struct DDirectory : public virtual Directory<arg,conv>, public virtual DFile<arg,conv>{
void foo(typename conv::Directory::UnionType& d){
}
};
template<class arg,class conv>
struct DFS : public virtual FS<arg,conv>{
typedef DFile<arg,conv> File;
typedef DDirectory<arg,conv> Directory;
};
template<class arg,template<class,class> class fsa,template<class,class> class fsb>
struct FSU{
typedef UnionBase<FS<arg,FSU>,fsa<arg,FSU>,fsb<arg,FSU> > FS;
typedef UnionBase<typename ::FS<arg,FSU>::Directory,typename fsa<arg,FSU>::Directory,typename fsb<arg,FSU>::Directory> Directory;
typedef UnionBase<typename ::FS<arg,FSU>::File,typename fsa<arg,FSU>::File,typename fsb<arg,FSU>::File> File;
};
typedef FSU<int,DFS,DFS> thing;
DDirectory<int,thing> d;
int main(int d,char** thing){
}
The error I get is:
invalid use of incomplete type 'struct DDirectory<int, FSU<int, DFS, DFS> >'
Here is UnionBase.h (its huge but don't worry all of this is working):
#ifndef prototypeInd_templates_UnionBase_h
#define prototypeInd_templates_UnionBase_h
#include <type_traits>
template<class Type, uint64_t time,class First,class... Array>
class IndexOf_{
static const bool isSame = std::is_same<First,Type>::value;
public:
static const uint64_t value = isSame ? time : IndexOf_<Type,time+1,Array...>::value;
};
template<class Type, uint64_t time, class First>
class IndexOf_<Type,time,First>{
public:
//static_assert(std::is_same<First,Type>::value,"Not contained in list");
static const uint64_t value = time;
};
template<class Type,class... Array>
using IndexOf = IndexOf_<Type,0,Array...>;
template<class Target, class First, class... Rest>
class ContainsType{
public:
static const bool value = std::is_same<Target, First>::value ? true : ContainsType<Target,Rest...>::value;
};
template<class Target, class First>
class ContainsType<Target,First>{
public:
static const bool value = std::is_same<Target, First>::value;
};
//Best is the highes so far while rest is the rest of the list
template <class Best,class First, class... Rest>
class GetMaxSize{
//typedef typename GetFirstType<Rest...>::value First;
static const bool FirstBigger = sizeof(First) > sizeof(Best);
public:
typedef typename std::conditional<FirstBigger,typename GetMaxSize<First,Rest...>::value,typename GetMaxSize<Best,Rest...>::value >::type value;
};
template<class Best, class First>
class GetMaxSize<Best,First>{
static const bool FirstBigger = sizeof(First) > sizeof(Best);
public:
typedef typename std::conditional<FirstBigger,First,Best >::type value;
};
template<class From,uint16_t index,class UT,class First,class... Array>
struct cast{
static void apply(From** t,UT* f){
if (index == f->GetActive()){
*t = &((First)(*f));
}
else{
cast<From,index+1,UT,Array...>::apply(t,f);
}
}
};
template<class From,uint16_t index,class UT,class First>
struct cast<From,index,UT,First>{
static void apply(From** t,UT* f){
if (index == f->GetActive()){
*t = &((First)(*f));
}
}
};
template<class... Values>
class UnionType{
typedef typename GetMaxSize<Values...>::value internal_t;
internal_t data;
uint16_t active;
public:
template<class CastFrom, class Dummy = typename std::enable_if<ContainsType<CastFrom,Values...>::value, int>::type >
UnionType(CastFrom&& d) : data(reinterpret_cast<internal_t&>(d)),active(IndexOf<CastFrom,Values...>::value){
}
template<class CastTo, class Condition = typename std::enable_if<ContainsType<CastTo,Values...>::value,int>::type >
operator CastTo const&() const{
return reinterpret_cast<const CastTo&>(data);
}
uint16_t GetActive() const{
return active;
}
//This one actually uses casting of the active data type
template<class CastTo, class Condition = typename std::enable_if<!ContainsType<CastTo,Values...>::value,int>::type >
explicit operator CastTo*() const{
CastTo temp;
CastTo* ret = &temp;
cast<CastTo,0,UnionType,Values...>::apply(&ret,this);
return ret;
}
};
namespace prototypeInd{namespace templates{
template<class Base, class Thing>
struct IsPublicBase{
static const bool value = std::is_base_of<Base,Thing>::value && std::is_convertible<Thing*,Base*>::value;
};
template<class Base, class First, class... Rest>
struct AllInheritFrom{
static const bool value = IsPublicBase<Base,First>::value ? AllInheritFrom<Base,Rest...>::value : false;
};
template<class Base, class First>
struct AllInheritFrom<Base,First>{
static const bool value = IsPublicBase<Base,First>::value;
};
template<template<class> class Function,class First,class... Args>
struct AllFullfill{
static const bool value = Function<First>::value ? AllFullfill<Function,Args...>::value : false;
};
template<template<class> class Function,class First>
struct AllFullfill<Function,First>{
static const bool value = Function<First>::value;
};
template<class Base, class... Rest>
class UnionBase{
static_assert(AllInheritFrom<Base,Rest...>::value, "All of the elements of UnionBase must have Base as a public base");
public:
typedef UnionType<Rest...> UnionType;
private:
UnionType internal;
public:
UnionBase() : internal(typename GetFirstType<Rest...>::value()){};
UnionBase(Base&& value) : internal(value){
}
operator UnionType&(){
return internal;
}
Base* operator ->() const{
//return 0;
return &((Base&)internal);
}
};
//template<class Base, class... Rest>
//using UnionBase = UnionBase_<Base,Rest...>*;
}}
#endif
So the real question is: what should I do to make this work? I am open to restructuring a little bit, but after hours of trying everything I can think of I am almost ready to scrap the whole thing and start again.
The problem is that in certain places of code your classes are really incomplete.
According to [class.mem]/1:
A class is considered a completely-defined object type (3.9) (or complete type) at the closing } of the class-specifier.
Within the class member-specification, the class is regarded as complete within function bodies,
default arguments, using-declarations introducing inheriting constructors (12.9), exception-specifications, and
brace-or-equal-initializers for non-static data members (including such things in nested classes). Otherwise
it is regarded as incomplete within its own class member-specification.
When applied to your code, this means in particular that the class is incomplete within function parameter lists. Now let's look at the definition of DDirectory::foo():
template<class arg,class conv>
struct DDirectory : public virtual Directory<arg,conv>, public virtual DFile<arg,conv>{
void foo(typename conv::Directory::UnionType& d){
}
};
In the instantiation DDirectory<int,thing> conv is FSU<int,DFS,DFS>, so instantiation of it involves instantiation of UnionBases inside, and eventially to this:
static_assert(AllInheritFrom<Base,Rest...>::value, "All of the elements of UnionBase must have Base as a public base");
where one of classes is DDirectory<int,thing>. Remember, all this happens in the deducing the type of the parameter of foo(), so DDirectory<int,thing> is incomplete, and that's what the compiler is saying.
You could try to move that static_assert for example to the constructor of UnionBase, but it doesn't solve other error which I think is impossible to fix, and the reason is the same:
error: invalid application of 'sizeof' to an incomplete type 'DDirectory<int, FSU<int, DFS, DFS> >'
static const bool FirstBigger = sizeof(First) > sizeof(Best);
^~~~~~~~~~~~~
Here is a minimized example reproducing the problem:
#include <type_traits>
template <typename T1, typename T2>
struct BiggerType {
using type = typename std::conditional<(sizeof(T1) > sizeof(T2)), T1, T2>::type;
};
template<typename T>
struct S {
using B = BiggerType<S, int>;
// This causes the instantiation of BiggerType,
// leading to calculation of sizeof(S) which is incomplete
void foo(const typename B::type& bt) {
}
};
int main() {
S<int> s;
}
Or in very compressed form,
template<typename T>
struct S {
// Same problem here
void foo(typename std::conditional<(sizeof(S) > sizeof(int)), S, int>::type&) {
}
};

Excessive qualifying of an enum type

In this code
template<typename ValueT, typename ErrorT = bool>
class ValueOrError
{
private:
enum class State
{
Undefined, OK, EndOfFile, InError
};
public:
........
template<typename U>
static ValueOrError
copyProblem(const ValueOrError<U, ErrorT>& other)
{
ValueOrError result;
result.error_ = other.error_;
result.state_ = other.state_;
// result.state_ = static_cast<State>(other.state_);
return result;
}
private:
template<typename U, typename E>
friend class ValueOrError;
State state_;
ValueT value_;
ErrorT error_;
};
g++ 4.8.3 gives an error at the state assignment. It complains
that a value of type ValueError<U>::State cannot be assigned
to a value of type ValueError<T>::State for different U and T.
The static cast gets around this. Is there a better way to
do this? The State type clearly doesn't vary with the template
parameter.
This is one way:
struct State
{
enum Enum{ Undefined, OK, EndOfFile, InError };
};
template< class ValueT, class ErrorT = bool>
class ValueOrError
: private State
{
public:

GCC template errors

I'm trying to port a C++ project to iOS. It compiles just fine in QtCreator on Linux and Windows and also on MSVC.
Now on Xcode/GCC, with a certain templated class I get the following error: "error: too few template-parameter-lists".
The code that causes this error looks something like this:
template <typename TA, typename TB, int Type>
class MyClassImpl
{
public:
MyClassImpl();
virtual int GetType() const
{
return type;
}
};
typedef MyClassImpl<float, int, 12> MyFloatIntClass;
MyFloatIntClass::MyFloatIntClass()
{
...
}
int MyFloatIntClass::GetType() const
{
return 22;
}
I'm guessing that something about the typedef syntax is illegal and GCC is more strict on the standard.
Can anybody tell me what exactly the problem is and how I can fix it?
As you're defining full specializations of methods of the respective class, you'll still need to prefix the definitions with template <>, which is the "template-parameter-lists" you're missing. Furthermore, the constructor must be named as the class is, so MyFloatIntClass::MyFloatIntClass() is illegal (as MyFloatIntClass is just an alias, not a class name). The following compiles fine for me (g++ 4.5.3):
template <typename TA, typename TB, int Type>
class MyClassImpl
{
public:
MyClassImpl();
virtual int GetType() const
{
return Type;
}
};
typedef MyClassImpl<float, int, 12> MyFloatIntClass;
template <>
MyFloatIntClass::MyClassImpl()
{
}
template <>
int MyFloatIntClass::GetType() const
{
return 22;
}
This is just a guess, but do you need to add template<>?
Since it's a template specialization, I believe it still needs to be a template.
ex.
template<>
MyFloatIntClass::MyClassImpl() {}
template<>
int MyFloatIntClass::GetType() const {
return 22;
}
EDIT: From modelnine's answer- turns out it needs the untypedef'd name for the ctor.
EDIT2: The following code works fine for me:
template <typename TA, typename TB, int Type>
class MyClassImpl
{
public:
MyClassImpl();
MyClassImpl(const MyClassImpl<TA, TB, Type>&);
virtual int GetType() const
{
return Type;
}
const MyClassImpl<TA, TB, Type>& operator=(const MyClassImpl<TA, TB, Type>&);
};
typedef MyClassImpl<float, int, 12> MyFloatIntClass;
template<>
MyFloatIntClass::MyClassImpl()
{
//
}
template<>
MyFloatIntClass::MyClassImpl( const MyFloatIntClass& rhs )
{
//
}
template<>
const MyFloatIntClass& MyFloatIntClass::operator=( const MyFloatIntClass& rhs )
{
return *this;
}
template<>
int MyFloatIntClass::GetType() const
{
return 22;
}

Getting non-const type in template

I have a template class that can (and sometimes has to) take a const type, but there is a method that returns a new instance of the class with the same type, but should be explicitly non-const. For example, the following code fails to compile
template<class T> class SomeClass {
public:
T val;
SomeClass(T val) : val(val) {}
SomeClass<T> other() {
return SomeClass<T>(val);
}
};
int main() {
SomeClass<const int> x(5);
SomeClass<int> y = x.other();
return 0;
}
because even though there's a copy on val during the constructor, it's copying to the same type - const int. Just like you can distinguish between T and const T in a template, is there a way to distinguish between T and "nonconst T"?
SomeClass<typename std::remove_const<T>::type> other()
{
return SomeClass<typename std::remove_const<T>::type>(val);
}
std::remove_const is from <type_traits> and is C++11. There's probably a boost::remove_const in Boost.TypeTraits, or you can even roll your own. It's also possible to use std::remove_cv.
You can either use std::remove_const if you are using c++ 11. Otherwise, you can use this:
struct <typename T>
struct remove_const
{
typedef T type;
};
struct <typename T>
struct remove_const<const T>
{
typedef T type;
};
Which does the same.
The problem in essence, is that there are two distinct types which are not strictly convertible.
You can use/return std::remove_const from type_traits:
#include <type_traits>
template<class T>
class SomeClass {
public:
T val;
SomeClass(T p) : val(p) {
}
SomeClass<typename std::remove_const<T>::type> other() {
return static_cast<SomeClass<typename std::remove_const<T>::type> >(val);
}
};
int main() {
SomeClass<const int>x(5);
SomeClass<int>y = x.other();
return 0;
}

Refactoring c++ template class based on template type

Given class Foo
template <typename T>
class Foo
{
public:
...other methods..
void bar()
{
...
m_impl.doSomething();
...
}
void fun()
{
...
m_impl.doSomethingElse();
...
}
void fubar()
{
...
}
private:
T m_impl;
};
I wanted to cater for situations where T is a boost::shared_ptr.
In this case the only change to class Foo is that it should invoke
m_impl->doSomething();
instead of
m_impl.doSomething();
I ended up defining FooPtr in the same header
template <typename T>
class FooPtr
{
public:
...other methods..
void bar()
{
...
m_pImpl->doSomething();
...
}
void fun()
{
...
m_pImpl->doSomethingElse();
...
}
void fubar()
{
...
}
private:
boost::shared_ptr<T> m_pImpl;
};
Now while the approach works for all classes that I want to use with Foo,
the problem is that I have a lot of duplicate code lying around and any changes
I make to Foo, I also have to make to FooPtr.
How can I refactor the code? E.g. Is there any way that I can determine at compile time if T is of type boost::shared_ptr, and then specialise just the bar and fun methods to invoke the -> operator?
Edit:
Thanks for all the answers so far! I just need some time to work through them all and see which solution is the best fit for our software.
Edit 2:
#Matthieu: This is the test code I was using
class FooImpl
{
public:
void doIt()
{
cout << "A" << std::endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Foo<FooImpl> foo;
foo.doSomething();
return 0;
}
Sylvain wrote a DRY solution, but I don't like abusing inheritance.
Using a wrapper class to uniformize the interface is easy, especially since pointer semantics work so well!
namespace details {
template <typename T>
struct FooDeducer {
typedef boost::optional<T> type;
};
template <typename T>
struct FooDeducer< T* > {
typedef T* type;
};
template <typename T>
struct FooDeducer< boost::shared_ptr<T> > {
typedef boost::shared_ptr<T> type;
};
} // namespace details
template <typename T>
class Foo {
public:
// methods
void doSomething() { impl->doIt(); }
private:
typedef typename details::FooDeducer<T>::type Type;
Type impl;
};
Here, relying on boost::optional which provides the OptionalPointee semantics, we nearly get the same behavior than pointers.
One point I'd like to emphasize though, is the difference in the copying behavior. boost::optional provides deep copy.
class A
{
public:
void doSomething() {}
};
template <typename T>
class Foo
{
public:
void bar()
{
Impl(m_impl).doSomething();
}
private:
template<typename P>
P& Impl(P* e)
{
return *e;
}
template<typename P>
P& Impl(std::shared_ptr<P> e)
{
return *e;
}
template<typename P>
P& Impl(P& e)
{
return e;
}
T m_impl;
};
You can write a caller class template, whose job is to call the function, either using syntax obj.f() or obj->f(), based on the type of obj.
Here is a small example that demonstrates this approach:
template<typename T>
struct caller
{
static void call(T &obj) { obj.f(); } //uses obj.f() syntax
};
template<typename T>
struct caller<T*>
{
static void call(T* obj) { obj->f(); } //uses obj->f() syntax
};
And this caller class template is used by this sample class:
template<typename T>
struct X
{
T obj;
X(T o) : obj(o) {}
void h()
{
caller<T>::call(obj); //this selects the appropriate syntax!
}
};
See this online running demo at ideone : http://www.ideone.com/H18n7
--
EDIT:
This is even more generic. Here you can even pass the function which you want to call in caller. Now caller is not hard-coded with the function to be called!
http://www.ideone.com/83H52
I really question whether you should be using a template here at all. Your template parameter has a very clear interface and therefore looks like you should just use an abstract base class.
Do you really need to have an instance? If you do need to change the way the object is represented, this should be done as a separate exercise and not part of the template that uses it.
You can introduce another intermediate template class, something like that:
template < typename T >
class FooBase
{
private:
T m_impl;
protected:
T& impl() { return m_impl; }
};
template < typename T >
class FooBase< boost::shared_ptr< T > >
{
private:
boost::shared_ptr< T > m_impl;
protected:
T& impl() { return *(m_impl.operator ->()); }
};
template < typename T >
class Foo : protected FooBase< T >
{
public:
void bar()
{
impl().DoSomething();
}
};
Now, you only have to code the Foo class only once. And you can specialize it for other smart pointers type by doing partial specialization on FooBase.
Edit: You can also use composition instead of having an inheritance relationship between Foo and FooBase (in which case, I'd probably rename it to FooHelper or something like that).
template < typename T >
class FooHelper
{
private:
T m_impl;
public:
T& impl() { return m_impl; }
};
template < typename T >
class FooHelper< boost::shared_ptr< T > >
{
private:
boost::shared_ptr< T > m_impl;
public:
T& impl() { return *(m_impl.operator ->()); }
};
template < typename T >
class Foo
{
private:
FooHelper< T > m_helper;
public:
void bar()
{
m_helper.impl().DoSomething();
}
};
You can use partial specialization.
template <typename T>
class Foo
{
public:
//...
};
template<typename T> class Foo<boost::shared_ptr<T>> {
//... implement specialization here
};