无法调用具有默认参数的函数特化,因为参数太少

Function specialization with default arguments can't be called because too few arguments

我有this代码

#include <iostream>
#include <type_traits>

enum class Color: char { Red = 'r', Yellow = 'y', Green = 'g' };

template<Color color>
auto say_my_name(unsigned times = 1) {
    for (unsigned i = 0; i < times; i++) {
        std::cout << static_cast<std::underlying_type_t<Color>>(color) << ' ';
    }
    std::cout << std::endl;
}

constexpr auto say_red = say_my_name<Color::Red>;

int main()
{
    say_my_name<Color::Yellow>(3);
    say_my_name<Color::Yellow>();
    say_red(2);
    say_red(); // too few arguments to function
}

我希望函数 say_redsay_my_name 的特化,这样我就可以轻松地在我的代码中调用它,而无需始终提供模板参数。

say_red(2) 工作正常,但 say_red() 无法编译并显示错误消息 “错误:函数参数太少”

有没有办法让我的代码在不指定参数的情况下编译?


作为旁注:如果这样可以解决问题,我也可以将模板参数转换为函数参数。我的问题是,std::bind 在 C++17 中不是 constexpr,所以这不适合我。
此外,我不想在 say_* 的每个声明中指定默认参数。你可以想象,这是一个例子,我的“现实生活”枚举有 8 个变体,所以我想写尽可能少的代码。

在调用站点替换默认参数。它们不是函数类型的一部分。因此,您需要“某物”来启用 say_red 的默认参数。您可以使用 lambda:

#include <iostream>
#include <type_traits>

enum class Color: char { Red = 'r', Yellow = 'y', Green = 'g' };

template<Color color>
auto say_my_name(unsigned times = 1) {
    for (unsigned i = 0; i < times; i++) {
        std::cout << static_cast<std::underlying_type_t<Color>>(color) << ' ';
    }
    std::cout << std::endl;
}

constexpr auto say_red = [](unsigned times = 1){
    say_my_name<Color::Red>(times);
};

int main()
{
    say_my_name<Color::Yellow>(3);
    say_my_name<Color::Yellow>();
    say_red(2);
    say_red(); // too few arguments to function
}

如果您不介意在每次调用时添加 (),您可以使用仿函数:

#include <iostream>
#include <type_traits>

enum class Color: char { Red = 'r', Yellow = 'y', Green = 'g' };

template<Color color>
struct say_my_name {
    void operator()(unsigned times = 1) const {
        for (unsigned i = 0; i < times; i++) {
            std::cout << static_cast<std::underlying_type_t<Color>>(color) << ' ';
        }
        std::cout << std::endl;
    }
};

using say_red = say_my_name<Color::Red>;

int main()
{
    say_my_name<Color::Yellow>()(3);
    say_my_name<Color::Yellow>()();
    say_red()(2);
    say_red()(); // too few arguments to function
}

如果您不喜欢额外的 (),您可以这样做:

using say_red = say_my_name<Color::Red>;
constexpr auto red_say = say_red{};

int main()
{
    red_say(2);
    red_say(); // too few arguments to function
}

请注意,您也可以使用构造函数代替 operator(),但使用 operator() 更灵活,因为它允许您 return 一个值。关键只是分两步进行特化和重载解析(特化仿函数,然后使用一个或零个参数调用 operator())。