简体   繁体   English

可变参数函数模板,其参数作为模板非类型传递

[英]Variadic function templates whose arguments are passed as template nontypes

The C++17 standard mentions a peculiar variadic function template that C ++ 17标准提到了一个独特的可变参数函数模板,

  • takes no normal function arguments but, instead, 不使用正常的函数参数,而是
  • takes nontype template arguments, 接受非类型模板参数

like f<200, 50, 6>() == 256 . f<200, 50, 6>() == 256

I thought, that's odd, let me see if I can code that myself. 我认为,这很奇怪,让我看看是否可以自己编写代码。 My code was elegant. 我的代码很优雅。 My elegant code however would not compile, so after two fruitless hours I wrote this ugly code: 但是,我的优雅代码无法编译,因此在两个徒劳的小时之后,我编写了以下丑陋的代码:

#include <iostream>

namespace {
    template<int A> constexpr int f() {return A;}
    template<int A, int B, int... C> constexpr int f() {
        if (sizeof...(C)) return A + f<B, C...>();
        else return A + B;
    }
}

int main() {
    int n = f<200, 50, 6>();
    std::cout << n << "\n";
    return 0;
}

This ugly code worked, and it was fun because it incidentally taught me sizeof...() . 这段丑陋的代码有效,而且很有趣,因为它偶然地教我sizeof...() It cannot be right, though, can it? 但是,这不可能是正确的吗?

Every time I try something simpler, the compiler balks, complaining about name-lookup conflicts or template redefinitions or something else of the kind. 每次我尝试更简单的操作时,编译器都会大惊小怪,抱怨名称查找冲突或模板重新定义或其他类似的情况。

My concept feels wrong. 我的概念感觉不对。 I suspect that I have missed the point. 我怀疑我错过了重点。 What point have I missed, please? 请问我错过了哪一点?

REFERENCE 参考

For information, in the standard (draft here ), the section that has provoked my question is sect. 有关信息,在标准( 此处为草稿)中,引起我问题的部分是本节。 5.13.8 (paragraphs 3 and 4). 5.13.8(第3和第4段)。 However, as far as I know, the provocation was incidental. 但是据我所知,这种挑衅是偶然的。 My question is not about the standard as such. 我的问题不是关于这样的标准。 My question is about the proper, elegant use of variadics, rather. 我的问题是关于适当地,优雅地使用变异函数。

NONCOMPILING EXAMPLE 非编译示例

If you want an example of my more elegant, noncompiling code, here is one: 如果您想要我更优雅,更未经编译的代码的示例,请参见以下示例:

namespace {
    template<> constexpr int f() {return 0;}
    template<int A, int... C> constexpr int f() {
        return A + f<C...>();
    }
}

After reading the compiler's error message, I understand why this particular code fails, so that is not my question. 阅读了编译器的错误消息后,我理解了为什么此特定代码失败,所以这不是我的问题。 My question, rather, is 我的问题是

  • how a variadic call like f<200, 50, 6>() ought properly to have been implemented and 应该如何正确实施像f<200, 50, 6>() 200,50,6 f<200, 50, 6>()这样的可变参数调用f<200, 50, 6>()以及
  • what concept I am consequently missing regarding C++ variadics. 因此,我对C ++变量缺少什么概念。

The C++17 way to write the function is C ++ 17编写函数的方式是

template<auto... Vals>
constexpr auto sum() noexcept(noexcept((Vals + ...)))
{
    return (Vals + ...);
}

Where template<auto... Vals> says we have a variadic template of values and (Vals + ...) is a fold expression which adds all of the values together (the outer () are required to make a valid fold expression). 其中template<auto... Vals>表示我们有一个可变的值模板,而(Vals + ...)是一个折叠表达式 ,它将所有值加在一起(外部()是创建有效折叠表达式所必需的) 。

I used auto... so that it isn't limited to a specific type. 我使用了auto...因此它不仅限于特定类型。 SFINAE can be added to constrain the template to only types that support addition if that is needed otherwise you'll just get a compiler error if not all types in the parameter pack can be added together. 如果需要,可以添加SFINAE来将模板限制为仅支持加法的类型,否则,如果不能将参数包中的所有类型都不能加在一起,则会出现编译器错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM