gpt4 book ai didi

c++ - 模板类非模板方法的早期实例化

转载 作者:行者123 更新时间:2023-12-03 06:57:12 26 4
gpt4 key购买 nike

考虑下面的类:

#include <vector>

template<class T>
struct my_struct {
my_struct() {}
explicit my_struct(T) {}
explicit my_struct(std::vector<T>) {}
};

int main() {
my_struct<const int> s1(1);
}

用例是第三个构造函数只能在 my_struct 的某些实例中调用,而不是在其他情况下(例如使用 const 类型)。这就是 main 中所做的事情:它被调用。

我收到编译器错误(GCC、Clang、Intel)。 GCC 错误消息:/usr/local/include/c++/10.2.0/bits/STL_vector.h:401:66: 错误:静态断言失败:std::vector 必须具有非常量、非 volatile 值类型

事实上,它与 std::vector 无关(但编译器很难给我们任何线索)。可以使用非常相似的代码来重现它:

class my_class {
static_assert(0, "should not be used");
};

template<class T>
struct my_struct {
my_struct() {}
explicit my_struct(T) {}
explicit my_struct(my_class) {}
};

int main() {
my_struct<int> s(1); // error
}

按照我的解释,问题是一旦实例化 my_struct ,它就会产生一个具体类型,并且编译器可能会实例化它的所有方法。在本例中,它实例化了 my_struct(my_class),因此它实例化了 my_class,因此我们得到了静态错误。

注意:但是我们可能会“幸运”:在 vector 情况下,仅调用 my_struct() 不会触发错误 (我猜与重载解析有关)

注意:我修复错误的方法是通过模板化构造函数而不是使用 vector :

template<class vector_type>
my_struct(vector_type) {}

我觉得它很丑,但没有其他想法。

  • 我对正在发生的事情的解释正确吗?
  • 语言是否需要/未定义此行为?还是编译器错误?
  • 如果是的话,我至少会称其为 C++17 中的语言缺陷。你同意吗?
  • 如果有,是否有语言缺陷报告?它在 C++20 中得到纠正吗?
  • 如果不是:您将如何解决该问题?是设计问题吗?
  • 我们是否可以期望编译器在不久的将来能够对正在发生的事情进行更详细的堆栈跟踪?至少提到为什么它需要实例化一个从未被当前的具体类调用的类型。
  • 最佳答案

    从 C++20 开始,您可以使用尾随的 require 子句引入的约束表达式,将 my_struct 类模板的给定实例化的第三个构造函数的实例化限制为某些对类模板的类型模板参数 T 进行谓词:

    #include <type_traits>
    #include <vector>

    template<class T>
    struct my_struct {
    my_struct() {}
    explicit my_struct(T) {}
    explicit my_struct(std::vector<T>) requires (!std::is_const_v<T>) {}
    };

    int main() {
    my_struct<const int> s(1);
    my_struct<int> t({1, 2});
    }

    与 C++20 之前的 std::enable_if_t SFINAE 方法相比,除了使用不太复杂的语法之外,它也不会强制您将构造函数设为模板函数,例如当构造函数是重载决策中的候选函数时,构造函数本身通过类型模板参数进行参数化,该类型模板参数参与推导过程。

    特别是,[temp.constr.constr]/2声明[强调我的]:

    [temp.constr.constr]/2

    In order for a constrained template to be instantiated([temp.spec]), its associated constraints shall be satisfied asdescribed in the following subclauses. [Note: Forming the name of aspecialization of a class template, a variable template, or an aliastemplate ([temp.names]) requires the satisfaction of its constraints.Overload resolution requires the satisfaction of constraints on functions and function templates. — end note]

    其中本例中的特定关联约束由 [temp.constr.decl]/3.3.4 涵盖:

    [temp.constr.decl]/3

    A declaration's associated constraints are defined as follows:

    • [...]
    • (3.3) Otherwise, the associated constraints are the normal form of a logical AND expression whose operands are in the following order:
      • [...]
      • (3.3.4) the constraint-expression introduced by a trailing requires-clause ([dcl.decl]) of a function declaration ([dcl.fct]).

    关于c++ - 模板类非模板方法的早期实例化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63810583/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com