可变参数模板的静态继承

问题描述

我正在尝试使用std::conditional来实现静态继承。 我的child类有两个可能的父类parent_one,应该根据传递的类型保存多个变量,而parent_two,则需要两种类型。我正在使用标签分派来区分要继承的类。

现在是问题所在。当我调用child并将其标记为从parent_one继承两种类型时,它可以按预期工作。但是,如果试图从child继承任何类型的数据到parent_one,则会出现错误

static_polymorphism.cpp: In instantiation of ‘class child<foo_type,int,double,float>’:
static_polymorphism.cpp:110:41:   required from here
static_polymorphism.cpp:99:7: error: wrong number of template arguments (4,should be 2)
   99 | class child : public std::conditional_t<
      |       ^~~~~
static_polymorphism.cpp:90:7: note: provided for ‘template<class T,class F> class parent_two’
   90 | class parent_two {
      |       ^~~~~~~~~~
static_polymorphism.cpp: In function ‘int main(int,char**)’:
static_polymorphism.cpp:111:9: error: ‘class child<foo_type,float>’ has no member named ‘log’
  111 |   first.log();

如果我理解正确,则编译器应基于我的标签分配来生成代码。这意味着它应该创建重载的类-来自parent_one的N(基于传递的类型)和来自parent_two的M(基于传递的类型)。但是由于某种原因(我不知道),它不接受类型的变量计数。你能告诉我我在做什么错吗?

实施在这里

using one_t = struct foo_type{};
using two_t = struct bar_type{};

template <typename ... TYPES>
class parent_one {
public:
  parent_one() = default;
  void log() {
    std::cout << "parent_one" << std::endl;
  }
};

template <typename T,typename F>
class parent_two {
public:
  parent_two() = default;
  void log() {
    std::cout << "parent_two" << std::endl;
  }
};

template <typename T,typename ... ARGS>
class child : public std::conditional_t<
    std::is_same_v<T,one_t>,parent_one<ARGS...>,parent_two<ARGS...>
  >
{
public:
  child() = default;
};

int main(int argc,char *argv[]) {
  child<one_t,float> first;
  first.log();

  child<two_t,int> second;
  second.log();
  return 0;
}

解决方法

std::conditional_t<
    std::is_same_v<T,one_t>,parent_one<ARGS...>,parent_two<ARGS...>
>

在检查条件之前,这里都验证了两个选择。 std::conditional_t并不神奇,它只是一个常规模板,它要求所有模板参数都有效,然后才能执行任何操作。

您需要将模板参数的替换延迟到父模板中,直到选择了其中一个选项为止。这是一种可能的解决方案:

template <template <typename...> typename T>
struct delay
{
    template <typename ...P>
    using type = T<P...>;
};
// ...
class child :
    public std::conditional_t<
        std::is_same_v<T,delay<parent_one>,delay<parent_two>
    >::template type<ARGS...> 
{
    // ...
};
,

您可能很经典:

git remote set-url origin https://author@git.example.org/org1/project1.git

(这两个专业可以与git-remote(1)组合成一个)。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...