2016-04-13 16 views
0

マイクロコントローラがSDカードとインターフェイスできるようにファイルシステムインターフェイスを作成しようとしています(ファイルシステムのすべてを最初から実装することにしました)。問題は、どのファイルシステムがカード上にあるのかわかりません.... FAT16、FAT32、NFTS、ext3、ectなどです。不完全な型の不正な使用(連鎖テンプレート化クラス)

私は以下の抽象クラスを作成しました:FileSystemFileDirectoryです。さて、それはすべて罰金とダンディーですが、私はnewオペレータの使用を避けたいので、マイクロコントローラを使用しています。

これは私のUnionBaseクラス(非常に有用な名前ではありません)の作成につながります。基本的に、このクラスは異なる派生クラスのすべての和集合を保持し、あなたはそれらの間で変換することができます:

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) 

今、私にはこれに合格するために、構造体がFileSystemUnion略してFSU呼ばれています。これは、基本的に必要なすべてのBaseUnionタイプを定義するだけです。

本当の問題は、再帰型のtypedef(私が知っていることは許されていません)なら型になるかもしれないということです。ここに私のコードの短縮バージョンは次のとおりです。

#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){ 

} 

私が手にエラーがある:ここでは invalid use of incomplete type 'struct DDirectory<int, FSU<int, DFS, DFS> >'

UnionBase.h(その巨大しかし、このすべてが働いている心配しないでください)です。

#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 

実際の質問は次のとおりです。この作業を行うにはどうすればよいですか?私は少しリストラをすることにはオープンしていますが、私が考えているすべてのことを試して何時間もしてから、私はすべてを取り払い、再び始める準備ができています。

+0

私は欠けている部分を置き換えた後[私はエラーを再現できませんでした](http://coliru.stacked-crooked.com/a/f7eda9b10e09555f)。あなたは[mcve]を投稿できますか? –

+0

@AntonSavin私はファイルを追加しました....それは非常に大きいですが、それはすべて働いています(私はこのプロジェクトとは別にテストしました。これはエラーを誘発する必要があります – DarthRubik

答えて

1

コードの特定の場所では、クラスが実際には不完全であるという問題があります。 【class.mem]/1によれば

クラスは、クラス指定子の閉鎖}で完全に定義されたオブジェクトのタイプ(3.9)(または完全なタイプ)であると考えられます。クラス部材仕様内 は、クラスは関数本体内に完了したとみなされ、 デフォルト引数、用い-宣言導入継承コンストラクタ(12.9)、例外仕様、及び ブレース、または、等しいです非静的データメンバー(ネストされたクラス内のものを含む)のための初期化子それ以外の場合は、 自身のクラス内では不完全とみなされますメンバ指定

コードに適用すると、特にクラスが関数パラメータリスト内で不完全であることを意味します。今度は、DDirectory::foo()の定義を見てみましょう:インスタンス化DDirectory<int,thing>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){ 
    } 
}; 

FSU<int,DFS,DFS>あるので、それのインスタンス化はUnionBaseの内部のインスタンス化を必要とする、とeventiallyこれに:の

static_assert(AllInheritFrom<Base,Rest...>::value, "All of the elements of UnionBase must have Base as a public base"); 

どこ1をクラスはDDirectory<int,thing>です。覚えておいてください。foo()という型の型を推測する際にこのようなことが起こるので、DDirectory<int,thing>は不完全であり、それはコンパイラが言っていることです。

あなたはUnionBaseのコンストラクタに例えばstatic_assertことを移動しようとすることができますが、それは私が解決することは不可能である、と理由は同じだと思う他のエラーが解決しない:ここでは

error: invalid application of 'sizeof' to an incomplete type 'DDirectory<int, FSU<int, DFS, DFS> >' 
static const bool FirstBigger = sizeof(First) > sizeof(Best); 
           ^~~~~~~~~~~~~ 

を問題を再現する最小限の例です:

#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; 
} 

または非常に圧縮された形で、

template<typename T> 
struct S { 
    // Same problem here 
    void foo(typename std::conditional<(sizeof(S) > sizeof(int)), S, int>::type&) { 
    } 
}; 
+0

ありがとう... – DarthRubik

関連する問題