【问题标题】:template class destructor for non-trivial types非平凡类型的模板类析构函数
【发布时间】:2021-04-27 19:25:17
【问题描述】:

我在玩 c++20 概念

https://godbolt.org/z/931xaeY45

#include <type_traits>

template<typename T>
class Optional
{
public:
    ~Optional() requires (!std::is_trivially_destructible_v<T>);

};

#include <cstdio>
int main()
{
    const char* bool_value[] = {"false", "true"};
    
    bool is_trivial = std::is_trivial_v<Optional<int>>;
    bool is_trivial_destructable = std::is_trivially_destructible_v<Optional<int>>;
    
    std::printf("std::is_trivial_v<Optional<int>> = %s\n", bool_value[is_trivial]);
    std::printf("std::is_trivial_destructable<Optional<int>> = %s\n", bool_value[is_trivial_destructable]);
}

输出:

std::is_trivial_v<Optional<int>> = false
std::is_trivial_destructable<Optional<int>> = false

但是,我希望析构函数不会被实例化,因为在这种情况下,requires (false) 是为模板参数int 生成的。

问:为什么~Optional() requires (false)Optional 类变得不平凡?

【问题讨论】:

    标签: c++ language-lawyer c++20 typetraits c++-concepts


    【解决方案1】:

    我阅读的标准and MSVC 说这是一个编译错误。

    在 C++20 中,这是:

    ~Optional() requires (!std::is_trivially_destructible_v<T>);
    

    是一个“预期的析构函数”。根据一系列规则,它可能会或可能不会成为实际的析构函数。但真正重要的是this rule

    如果一个类没有用户声明的预期析构函数,则预期析构函数被隐式声明为默认值 ([dcl.fct.def])。

    你的类一个“用户声明的预期析构函数”。因此,没有“隐式声明为默认”的构造函数永远

    这很重要,因为this rule kicks in:

    在类的定义结束时,在该类中声明的预期析构函数之间执行重载决议,该析构函数带有一个空参数列表,以选择该类的析构函数,也称为选定析构函数。 如果重载解析失败,则程序格式错误。

    由于T 可以简单地破坏,重载决议不能调用你的预期破坏者,因为requires 约束会杀死它。并且没有其他析构函数可以找到。所以它不应该编译,而且 GCC 可能还没有正确实现规则。

    无论如何,你需要提供一个默认的替代析构函数:

    ~Optional() requires (!std::is_trivially_destructible_v<T>);
    ~Optional() = default;
    

    【讨论】:

      【解决方案2】:

      据我了解,您必须为Tdefault (seems to work in GCC) 提供一个可简单破坏类型的替代方案

      template<typename T>
      class Optional {
      public:
        // Chosen for not trivially destructible types
        ~Optional() requires (not std::is_trivially_destructible_v<T>);
        // Chosen for everything else (trivially destructible types)
        ~Optional() = default;
      };
      

      在您的情况下,只有一个选项未设置为 default,这使其默认不可破坏。

      【讨论】:

      • Nicol Bolas 的回答更雄辩、更详细地解释了它。
      猜你喜欢
      • 1970-01-01
      • 2022-01-23
      • 2021-07-20
      • 2018-03-24
      • 2015-09-02
      • 1970-01-01
      • 1970-01-01
      • 2016-06-01
      • 1970-01-01
      相关资源
      最近更新 更多