延迟成员变量类型定义,直到另一个 class 从它继承

Delay a member variables type definition till another class inherits from it

我正在尝试将成员变量类型声明为派生 class 控制的东西 - 而无需将类型作为模板传输。

#include <tuple>
#include <iostream>  
#include <ostream>
using namespace std;

template<class DERIVED_TYPE>
struct haveChildren
{   
    const std::tuple<int, DERIVED_TYPE::innerContext > myChildren;

    haveChildren(int a, char b) : myChildren(5, DERIVED_TYPE::innerContext{ a, b }) {}

    friend ostream& operator<< (ostream& streamReceiver, const haveChildren<DERIVED_TYPE>& streamSender)
    {
        int myInt;  int myChar;
        std::tie(myInt, myChar) =   std::get<1>(streamSender.myChildren);

        return streamReceiver << "My int is " << myInt << " my char is " << ((char)myChar);
    }
};

struct haveChildrenCharAndInt : public haveChildren<haveChildrenCharAndInt>
{
    typedef    std::tuple<char, int> innerContext;

    haveChildrenCharAndInt() : haveChildren<haveChildrenCharAndInt>(10,'x') {}
};

int main(int argc, char* argv[])
{
    cout << haveChildrenCharAndInt();
    return 0;
}

那当然不会编译-但我希望你明白我想做什么。

可以通过像这样将类型作为模板参数传递来完成:

template<class DERIVED_TYPE,typename A,typename B>
struct haveChildren
{   
    const std::tuple<int, std::tuple<A, B>  > myChildren;

    haveChildren(int a, char b) : myChildren(5, std::tuple<A, B> { a, b }) {}

    friend ostream& operator<< (ostream& streamReceiver, const haveChildren<DERIVED_TYPE,A,B>& streamSender)
    {
        int myInt;  int myChar;
        std::tie(myInt, myChar) =   std::get<1>(streamSender.myChildren);

        return streamReceiver << "My int is " << myInt << " my char is " << ((char)myChar);
    }
};

struct haveChildrenCharAndInt : public haveChildren<haveChildrenCharAndInt,char,int>
{
    typedef    std::tuple<char, int> innerContext;

    haveChildrenCharAndInt() : haveChildren<haveChildrenCharAndInt,char,int>(10,'x') {}
};

int main(int argc, char* argv[])
{    
    cout << haveChildrenCharAndInt();
    return 0;
}

但是这个解决方案并不好,因为 class 作为成员变量应该具有的类型是 classes 并且它们是在之后创建的。

你们有没有人知道一种设计或技巧,可以让一个类型的成员变量在 class 从它继承之前没有定义 - 而不将类型作为模板参数传递?

您可以稍微改变您的设计并使其正常工作。

#include <tuple>
#include <iostream>  
#include <ostream>
using namespace std;

// A helper class template to let you define the inner
// context of a derived type before the derived type is
// defined.
template <class DERIVED_TYPE> struct InnerContext;

template<class DERIVED_TYPE>
struct haveChildren
{   
   // Use the helper class template to get the inner context 
   // type of DERIVED_TYPE.
   using DerivedInnerContext = typename InnerContext<DERIVED_TYPE>::type;
   std::tuple<int, DerivedInnerContext> myChildren;

   haveChildren(int a, char b) : myChildren(5, DerivedInnerContext{ a, b }) {}

   friend ostream& operator<< (ostream& streamReceiver, const haveChildren& streamSender)
   {
      int myInt;  int myChar;
      std::tie(myInt, myChar) =  std::get<1>(streamSender.myChildren);

      return streamReceiver << "My int is " << myInt << " my char is " << ((char)myChar);
   }
};

// Define the inner context of haveChildrenCharAndInt before
// haveChildrenCharAndInt is defined.
struct haveChildrenCharAndInt;
template <> struct InnerContext<haveChildrenCharAndInt>
{
   using type = std::tuple<char, int>;
};

// haveChildrenCharAndInt is now simplified.
struct haveChildrenCharAndInt : public haveChildren<haveChildrenCharAndInt>
{
   haveChildrenCharAndInt() : haveChildren<haveChildrenCharAndInt>(10,'x') {}
};

int main(int argc, char* argv[])
{
   cout << haveChildrenCharAndInt();
   return 0;
}

您可以将内部上下文作为类型特征进行传输:

template<typename Type>
struct inner_context;

并在基础 class 中使用它作为:

template<class Derived>
struct base {
    using children_type = typename inner_context<Derived>::type;
    const std::tuple<int, children_type> children;

    base(int a, char b) : children(5, children_type{ a, b }) {}
};

然后每当你定义一个新类型时,你就声明了该类型的特化:

struct derived;

template<>
struct inner_context<derived> {
    using type = std::tuple<char, int>;
};

最后是类型本身:

struct derived : public base<derived> {
    derived() : base(10,'x') {}
};

Live demo