是否可以在编译时检测函数的默认参数?

时间:2017-03-21 07:09:10

标签: c++ templates c++17 typetraits

#include <thread>
#include <functional>

using namespace std;

void f(int n = 7)
{}

void g(function<void()> fn)
{
    fn(); // same as f(7)
}

template<typename Callable>
auto GetDefaultArg(Callable fn, size_t arg_ordinal)
{
    // What to put here?
}

int main()
{
    auto fn = bind(f, GetDefaultArg(f, 1));
    g(fn);  
}

如上面的代码所示,我想实现一个模板函数GetDefaultArg来检测函数的默认副作用。

目前的C ++有可能吗?

2 个答案:

答案 0 :(得分:5)

否则您无法在编译时检测到默认参数。

您已在函数定义中声明了默认参数。但是默认参数没有链接到函数本身,而是在调用函数的范围内已知函数的声明。

否则说明:您可以为同一个函数设置不同的默认参数集。

答案 1 :(得分:3)

要添加到Chrisophe's excellent answer,我将举例说明他的意思。

我们可以稍后使用其他默认值重新声明一个函数!

这是什么意思?

让我们从函数声明开始:

// initial declaration; nothing defaulted
void foo(int a, char b, bool c, double d);

我有一些没有默认参数的函数foo。 我写了一个调用foo

的函数
void CallFoo1()
{
    // no default params
    foo(1, 'b', true, 2.0);
}

它必须为foo中的每个参数提供一个参数。

但是,现在我可以重新声明 foo(只要我尚未定义它),并将最后一个参数设为默认值:

// add default for last argument
void foo(int a, char b, bool c, double d= 2.0);

然后我编写调用foo的另一个函数。除了这次我可以将最后一个参数留空:

void CallFoo2()
{
    foo(1, 'b', true);
}

我可以继续这样做,每次都使用新的默认值重新声明:

// add default for third argument
void foo(int a, char b, bool c=true, double d);

void CallFoo3()
{
    foo(1, 'b');
}

// add default for second argument
void foo(int a, char b='b', bool c, double d);

void CallFoo4()
{
    foo(1);
}

// add default for first argument
void foo(int a=1, char b, bool c, double d);

void CallFoo5()
{
    // everything is defaulted!
    foo();
}

foo的最后一次重新声明之后,foo的声明包含默认值的并集(注意:我无法重新默认值)。

最后我可以提供foo的定义:

void foo(int a, char b, bool c, double d)
{
    std::cout << "a = " << a << " b = " << b << " c = " << std::boolalpha << c << " d = " << d << std::endl;
}

让我们试一试:

int main()
{
    CallFoo1();
    CallFoo2();
    CallFoo3();
    CallFoo4();
    CallFoo5();
}

输出:

a = 1 b = b c = true d = 2
a = 1 b = b c = true d = 2
a = 1 b = b c = true d = 2
a = 1 b = b c = true d = 2
a = 1 b = b c = true d = 2

Live Demo