模板参数的困惑

huangapple go评论59阅读模式
英文:

Confusion about template parameters

问题

  1. template in C++ is designed to be flexible and can work with both type parameters and non-type parameters (such as values or objects) based on how it's declared. In your examples, template<typename A> and template<int v, Unit u> are templates with type and non-type parameters, respectively. When you define a template, you specify the kind of parameters it accepts.

    In the case of Measure_add, M1 and M2 are indeed types (they are expected to be types like Measure<int, Unit::m>), but they have a member value which is a constant expression. This allows you to access M1::value and M2::value. This usage is allowed because you've defined the Measure struct with these member variables.

  2. Accessing M1::value and M2::value in the template struct Measure_add is possible because you've constrained the template parameters M1 and M2 to be types that have the value member variable. If you were to use other parameters that don't contain the value attribute, it would indeed cause a compilation error because the compiler wouldn't find the value member in those types. So, the code is designed to work specifically with types that have the expected member attributes, and it enforces this constraint through the template parameter types.

英文:

Lately I practiced the use of template in c++, and I am confused about one of the template parameters during the process.

For instance, in the following code, the input A of template&lt;typename A&gt; served as a 'type' to construct function and variables.

template &lt;typename A&gt;
A add_simple(A a, A b)
{
    return a + b;
}

However, in the following example, a unit conversion operation, it seems the input M1 and M2 serve as objects. In main(), I've shown how the struct is expected to be called.

// create a template struct Measure with value and unit. e.g. Measure&lt;int, Unit&gt;::value
template&lt;int v, Unit u&gt; struct Measure{
    static const int value=v;
    static const Unit unit=u;
};

// Conversion struct. expected input two &#39;Measure&#39; objects. 
template &lt;typename M1, typename M2&gt; 
struct Measure_add {
public:
    // other implementation

    static constexpr int value=M1::value+M2::value;
};

int main(int, char**) {

    std::cout &lt;&lt; Measure_add&lt; Measure&lt;10,Unit::m&gt;,
        Measure&lt;20,Unit::m&gt; &gt;::value &lt;&lt; std::endl;

}

So my confusion about template is:

  1. Is &lt;template&gt; designed to be such flexible that it dynamically distinguish the input so both a 'type' input and 'object' input works. Or the difference met here because the expected inputs are constructed template input Measure? As a result, M1 and M2 are still 'type', Measure. And in this case, why M1::value is available if M1 is a type instead of an object?

  2. Why is it available to get access to M1::value or M2::value in template struct Measure_add though the inputs are unknown to such struct. In other words, if I input other parameters which don't contain attribute value, would it cause problem?

答案1

得分: 1

在你的代码中,`M1`  `M2` 都是类型模板参数。你可以说 `M::value` 的原因是 `value` 是在类型 `M` 中被替换的静态数据成员。这就是 `static` 数据成员的要点:你不需要一个对象来访问它的值。这与模板无关:

```cpp
struct M {
    static constexpr int value = 0;
};

int foo() {
    return M::value;   // 可行
}

M1M2 不受限于作为 Measure 模板的特化:它们可以是任何具有静态 value 数据成员的类型。对于不满足此条件的其他类型,你将会得到一个编译错误。

std::cout <<
    Measure_add<
        std::integral_constant<int, 10>,
        std::integral_constant<int, 20>
    >::value;  // 编译通过,输出 30

以及

std::cout << 
    Measure_add<
        Measure<10, Unit::m>,
        std::integral_constant<int, 20>
    >::value;  // 编译通过,输出 30,但没有意义

<details>
<summary>英文:</summary>

In your code both `M1` and `M2` are type template parameters. The reason why you can say `M::value` is that `value` is a static data member in a type that is substituted for `M`. That&#39;s the point of a `static` data member: you don&#39;t need an object to access its value. This is not related to templates:

struct M {
static constexpr int value = 0;
};

int foo() {
return M::value; // OK
}


`M1` and `M2` are not constrained to being specializations of `Measure` template: they can be any types that have a static `value` data member. For other types that don&#39;t satisfy this condition you&#39;ll simply get a compilation error.

std::cout <<
Measure_add<
std::integral_constant<int, 10>,
std::integral_constant<int, 20>
>::value; // compiles, prints 30

and

std::cout <<
Measure_add<
Measure<10, Unit::m>,
std::integral_constant<int, 20>
>::value; // compiles, prints 30, but makes no sense


</details>



huangapple
  • 本文由 发表于 2023年1月9日 05:20:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/75051389.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定