代码之家  ›  专栏  ›  技术社区  ›  NoSenseEtAl

C++20中不允许结构的模板重载的设计原因是什么?

  •  0
  • NoSenseEtAl  · 技术社区  · 4 年前

    在回答我之前的问题时,我了解到C++20概念确实 允许在结构模板参数上重载,例如这不起作用:

    #include <concepts>
    
    template <std::integral>
    struct S{
    
    };
    template <std::floating_point>
    struct S{
    };
    

    奇怪的是,clang error是这样的,但这并不重要,因为我知道C++标准不允许此代码工作:

    模板重新声明中的类型约束不同

    我发现这种不工作的编写模板的方式非常自然,所以我想知道这是否被考虑过,如果是,为什么在标准化过程中被拒绝?

    附言:这似乎在C++20中有效,但我发现它更丑陋

    #include <concepts>
    #include <iostream>
    
    template <typename T>
    requires std::integral<T> || std::floating_point<T>
    struct S{
    
    };
    template <std::integral T>
    struct S<T>{
        static constexpr char msg[] = "i";
    
    };
    template <std::floating_point T>
    struct S<T>{
        static constexpr char msg[] = "fp";
    };
    
    int main() {
        std::cout <<  S<char>::msg << std::endl;
        std::cout <<  S<double>::msg << std::endl;
    }
    
    0 回复  |  直到 4 年前
        1
  •  10
  •   Davis Herring    4 年前

    C++从来没有重载过 或类模板。类当然没有可以用来选择重载的参数,但也不能写入

    template<class> struct A {};
    template<int> struct A {};
    

    即使每 模板id 很明显哪一个是合适的( A<int> vs。 A<1> )。这一限制有几个原因:

    1. 这是不可能写的 通用的 使用在实例化时选择的上述重载之一的代码:对于 A<…> ,参数是类型还是值是固定的,即使它是依赖的。(如果过载是 template<int&> template<float&> 当然。)
    2. 偶尔会提到模板 没有 任何模板参数,并且在两者都适用的情况下,没有语法可供选择。其中一个上下文是模板模板参数(可能属于 template<class...> class 品种);另一种是CTAD。
    3. 一些 ADL -类似的机制对于支持在使用模板的泛型代码之后重载应用程序类型的类模板的情况是必要的。
    4. 一般来说,无法确定 部分专业化 相关。

    C++20行为只是这个模型的延续;添加泛型并不难

    template<class> struct S;  // undefined
    

    作为保护伞来保护被宣布为

    template<std::integral I>
    struct S<I> {};
    template<std::floating_point F>
    struct S<F> {};
    
        2
  •  6
  •   Sebastian    4 年前

    模板参数推导不适用于 明确的 类模板的专业化(与函数模板相比)。这与概念本身无关。您将需要 template<> 关键字和 <T> 参数

    我不知道,也找不到任何标准的建议来进一步缩短这一点。

    在以下代码中,特别是的主要定义 S 比问题中的工作版本短得多。

    #include <concepts>
    
    template <typename T>
    concept Number = std::integral<T> || std::floating_point<T>;
    
    
    template <Number T>
    struct S;
    
    template <std::integral T>
    struct S<T>{
    };
    
    template <std::floating_point T>
    struct S<T>{
    };
    

    上面的代码编译并运行。

    通过使用 Number 用于实例化的错误消息的第一行 s 例如。 std::string 是:

    error: template constraint failure for 'template<class T> requires Number<T> struct S'

    这很容易理解并切中要害(以下几行中有更多详细信息 std::字符串 不是 integral || floating_point )。因此,有可能为错误的实例化构建错误消息级别(例如,您可以定义自己的 integral 列出允许的整数类型的概念)。