可变参数模板,完美转发到带有默认参数的函数

发布于 2024-12-17 19:37:45 字数 2044 浏览 1 评论 0原文

我一直在使用可变参数模板,它充当 C 和 C++ 之间的接口中的异常防火墙。该模板仅接受一个函数,后跟 N 个参数,并在 try catch 块内调用该函数。这一直工作得很好,不幸的是我现在希望调用的函数之一需要一个额外的默认参数。因此,函数名称未解析,模板无法编译。

错误是:

perfect-forward.cpp: 在函数'void FuncCaller(Func, Args&...) [with Func = void (*)(const std::basic_string&, double, const std::vector&), Args = {const char (&)[7], double}]':
Perfect-forward.cpp:69:41:从这里实例化
Perfect-forward.cpp:46:4:错误:函数参数太少

代码的简化版本如下:

template< class Func, typename ...Args >
void FuncCaller( Func f, Args&&... params )
{
   try
   {
       cout << __func__ << " called\n";
       f(params...);
   }
   catch( std::exception& ex )
   {
       cout << "Caught exception: " << ex.what() << "\n";
   }
}

void Callee( const string& arg1, double d, const vector<int>&v = vector<int>{} )
{
   cout << __func__ << " called\n";
   cout << "\targ1: " << arg1 << "\n";
   cout << "\td: " << d << "\n";
   cout << "\tv: ";
   copy( v.begin(), v.end(), ostream_iterator<int>( cout, " "  ) );
   cout << "\n";
}

int main()
{
   vector<int> v { 1, 2, 3, 4, 5 };

   FuncCaller( Callee, "string", 3.1415, v );
   FuncCaller( Callee, "string", 3.1415 );  **// Fails to compile**

   return 0;
} 

该代码应该工作还是我对编译器的期望过高?

注意:我已经测试了使用具有默认参数的构造函数进行完美转发,并且代码按预期进行编译和工作,

即:

template<typename TypeToConstruct> struct SharedPtrAllocator 
{
    template<typename ...Args> shared_ptr<TypeToConstruct> 
        construct_with_shared_ptr(Args&&... params) {
        return std::shared_ptr<TypeToConstruct>(new TypeToConstruct(std::forward<Args>(params)...));
    };
};

在使用 2 或 3 个参数调用 cfollowing 构造函数时有效...

MyClass1( const string& arg1, double d, const vector<int>&v = vector<int>{} )

I have been using a variadic template that acts as an exception firewall in an interface between C and C++. The template simply takes a function, followed by N arguments and calls the function inside a try catch block. This has been working fine, unfortunately one of the functions I wish to call now takes an additional default argument. As a result the function name is not resolved and the template fails to compile.

The error is:

perfect-forward.cpp: In function ‘void FuncCaller(Func, Args&& ...) [with Func = void (*)(const std::basic_string<char>&, double, const std::vector<int>&), Args = {const char (&)[7], double}]’:
perfect-forward.cpp:69:41: instantiated from here
perfect-forward.cpp:46:4: error: too few arguments to function

A simplified version of the code is as follows:

template< class Func, typename ...Args >
void FuncCaller( Func f, Args&&... params )
{
   try
   {
       cout << __func__ << " called\n";
       f(params...);
   }
   catch( std::exception& ex )
   {
       cout << "Caught exception: " << ex.what() << "\n";
   }
}

void Callee( const string& arg1, double d, const vector<int>&v = vector<int>{} )
{
   cout << __func__ << " called\n";
   cout << "\targ1: " << arg1 << "\n";
   cout << "\td: " << d << "\n";
   cout << "\tv: ";
   copy( v.begin(), v.end(), ostream_iterator<int>( cout, " "  ) );
   cout << "\n";
}

int main()
{
   vector<int> v { 1, 2, 3, 4, 5 };

   FuncCaller( Callee, "string", 3.1415, v );
   FuncCaller( Callee, "string", 3.1415 );  **// Fails to compile**

   return 0;
} 

Should this code work or am I expecting too much from the compiler?

Note: I have tested the use of perfect forwarding with constructors that have default arguments and the code compiles and works as expected,

i.e.:

template<typename TypeToConstruct> struct SharedPtrAllocator 
{
    template<typename ...Args> shared_ptr<TypeToConstruct> 
        construct_with_shared_ptr(Args&&... params) {
        return std::shared_ptr<TypeToConstruct>(new TypeToConstruct(std::forward<Args>(params)...));
    };
};

works when calling the cfollowing constructor with 2 or 3 arguments...

MyClass1( const string& arg1, double d, const vector<int>&v = vector<int>{} )

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

云淡月浅 2024-12-24 19:37:45

我认为没有任何方法可以实现这一目标。默认参数值不是函数签名的一部分。它们只是代码生成的简写,当您按字面调用函数时,编译器会对其进行扩展。同样,std::bind 也不会选择默认参数。

I don't think there's any way this can be achieved. The default argument values are not part of the function signature. They're only code-generation short-hands that are expanded by the compiler when you call the function literally. Similarly, std::bind won't pick up default arguments, either.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文