理解 SFINAE:部分专门化类之外的成员函数声明以及可变参数类中的模板

问题描述 投票:0回答:1

我想做的事:

创建一个“指令集”对象

  • 由其他地方的指针控制
  • 保存可变数量的指令对象,其类型满足概念“is_instruction_type”
  • 具有“提取”功能,可生成仅包含特定类型指令的新“指令集”

我尝试通过在可变参数类上使用继承来实现这一点,以便可以使用递归来存储正确类型的每条指令;然后,指向“InstructionSet<>”类型的指针可以在其上使用虚拟函数,以便能够访问继承的底部,并在该对象上递归。

//Define recursively
template<typename...Args> requires (is_instruction_type<Args> && ...)
class InstructionSet;


//Base
template<>
class InstructionSet<> 
{
public:
    InstructionSet() {};
    virtual ~InstructionSet() {};

    template<typename U>
    auto extract()
    {
        return extractHelper()->extract();
    };

protected:
    virtual InstructionSet<>* extractHelper();
};

//Recur
template<typename T, typename ...Rest> requires is_instruction_type<T>
class InstructionSet<T, Rest...> : public InstructionSet<Rest...>
{
public:
    InstructionSet(T&& t, Rest&&...rest);
    InstructionSet(T&& t, InstructionSet<Rest...>&& set);

    virtual ~InstructionSet() {};

    template<typename U> requires std::same_as<T, U>
    auto extract();

    template<typename U> requires !std::same_as<T, U>
    auto extract();


    virtual InstructionSet<T, Rest...>* extractHelper()
    {
        return this;
    };

private:
    T _instruction;

};



template<typename T, typename ...Rest> requires is_instruction_type<T>
inline InstructionSet<T, Rest...>::InstructionSet(T&& t, Rest&& ...rest) : InstructionSet<Rest...>(std::forward<Rest>(rest)...),
_instruction(std::forward<T>(t))
{

}
template<typename T, typename ...Rest> requires is_instruction_type<T>
inline InstructionSet<T, Rest...>::InstructionSet(T&& t, InstructionSet<Rest...>&& set)
{
    _instruction = std::forward<T>(t);
    std::construct_at((InstructionSet<Rest...>*)this, std::move(set));
}


template<typename T, typename ...Rest> requires is_instruction_type<T>
template<typename U> requires std::same_as<T, U>
auto InstructionSet<T, Rest...>::extract<U>()
{
    return InstructionSet(_instruction, std::move(((InstructionSet<Rest...>*)this)->extract()));
}

template<typename T, typename ...Rest> requires is_instruction_type<T>
template<typename U> requires (!std::same_as<T, U>)
auto InstructionSet<T, Rest...>::extract<U>()
{
    return ((InstructionSet<Rest...>*)this)->extract();
}

我有两个问题:

  • 如何在多个模板下的类外部定义“提取”?
  • 在部分专门化的类定义中应该如何对待类成员? (还应该包含完整的类定义吗?)

我尝试了包含/排除尖括号的不同组合,并尝试将函数定义移动到类内部,但都抛出错误。

我认为我了解具有类型定义和静态变量的类的 SFINAE 基础知识,但是对于更复杂的类,我感到困惑,并且似乎找不到很多示例。

c++ variadic-templates sfinae
1个回答
0
投票

我认为你可以通过不进行专业化并使用

std::tuple
来简化它。

示例:

template <class... Ts>
    requires(is_instruction_type<Ts> && ...)
class InstructionSet {
public:
    template <class... Us>
    InstructionSet(Us&&... us) : _instructions{std::forward<Us>(us)...} {}

    virtual ~InstructionSet() = default;

    template <std::size_t... Is>    // extract by index
    InstructionSet<std::tuple_element_t<Is, std::tuple<Ts...>>...> extract();

    template <class... Us>          // extract by unique types
    InstructionSet<Us...> extract();

private:
    std::tuple<Ts...> _instructions;
};

template <class... Ts>
    requires(is_instruction_type<Ts> && ...)
template <std::size_t... Is>
InstructionSet<std::tuple_element_t<Is, std::tuple<Ts...>>...>
InstructionSet<Ts...>::extract() {
    return {std::get<Is>(_instructions)...};
}

template <class... Ts>
    requires(is_instruction_type<Ts> && ...)
template <class... Us>
InstructionSet<Us...>
InstructionSet<Ts...>::extract() {
    return {std::get<Us>(_instructions)...};
}

演示

© www.soinside.com 2019 - 2024. All rights reserved.