Gui*_*cot 6 c++ variadic-templates c++11
使用可变参数模板我遇到了一个非常奇怪的问题.似乎错误的包装被扩大了.这是一段代码片段:
#include <tuple>
template<typename...>
struct types {};
template<typename = types<>>
struct Base;
template<typename... Args1>
struct Base<types<Args1...>> {
template<typename... Args2>
static auto construct(Args1... args1, Args2&&... args2)
-> decltype(std::make_tuple(args1.forward()..., std::declval<Args2>()...))
{
return std::make_tuple(args1.forward()..., std::forward<Args2>(args2)...);
}
};
struct Derived : Base<> {};
int main() {
auto test = &Derived::construct<char const(&)[7]>;
}
Run Code Online (Sandbox Code Playgroud)
我收到此错误:
13 : <source>:13:43: error: request for member 'forward' in 'args2#0', which is of non-class type 'const char [7]'
-> decltype(std::make_tuple(args1.forward()..., std::declval<Args2>()...))
~~~~~~^~~~~~~
13 : <source>:13:43: error: request for member 'forward' in 'args2#0', which is of non-class type 'const char [7]'
<source>: In function 'int main()':
22 : <source>:22:27: error: unable to deduce 'auto' from '& construct<const char (&)[7]>'
auto test = &Derived::construct<char const(&)[7]>;
^~~~~~~~~~~~~~~~~~~~~~~~~~~
22 : <source>:22:27: note: could not resolve address from overloaded function '& construct<const char (&)[7]>'
Compiler exited with result code 1
Run Code Online (Sandbox Code Playgroud)
但是,当包中包含值时,它不会发生:
struct HasForward { int forward() { return 0; } };
struct Derived : Base<types<HasForward>> {};
Run Code Online (Sandbox Code Playgroud)
这是First snippet live和Second snippet live
这段代码出了什么问题?这是编译器错误吗?有没有办法克服它并让第一包空着?
这是编译器错误吗?有什么办法可以克服它并让第一个包空着吗?
它看起来像是您的编译器中的错误。
要解决此问题,您可以使用函数声明(无需定义),如以下示例中所示,并使用它来测试您的参数:
template<typename... Args1>
class Base<types<Args1...>> {
template<typename... T, typename... U>
static auto ret(types<T...>, types<U...>)
-> decltype(std::make_tuple(std::declval<T>().forward()..., std::declval<U>()...));
public:
template<typename... Args2>
static auto construct(Args1... args1, Args2&&... args2)
-> decltype(ret(types<Args1...>{}, types<Args2...>{}))
{
return std::make_tuple(args1.forward()..., std::forward<Args2>(args2)...);
}
};
Run Code Online (Sandbox Code Playgroud)
有点难看,但是当你的第一个包是空的(也按照要求在 C++11 中)并且所有内容都应该被链接器丢弃时,它就可以工作。
- -编辑
正如@WF 在评论中所建议的(感谢您的建议,我没有注意到),实现这一点甚至更容易。
只需按如下方式定义您的函数:
static auto construct(Args1... args1, Args2&&... args2)
-> decltype(std::make_tuple(std::declval<Args1>().forward()..., std::declval<Args2>()...))
{
return std::make_tuple(args1.forward()..., std::forward<Args2>(args2)...);
}
Run Code Online (Sandbox Code Playgroud)