我只是天真地写了这个:
#include <stdio.h>
template< class... Args >
auto format_for( Args... args, int last_arg )
-> char const*
{
// using Specifier = char const [3];
// static Specifier const s[] = { {'%', 'f'+(0*args), ' '}..., {'%', 'f', 0} };
return reinterpret_cast<char const*>( "" );
}
auto main() -> int
{
printf( "'%s'\n", format_for( 5, 2, 1 ) );
}
Run Code Online (Sandbox Code Playgroud)
它崩溃了Visual C++ 2015更新1,一个ICE(内部编译器错误),并且g ++ 5.1.0维护该函数只接受一个参数,可能是因为忽略了Args无法匹配此模板参数:
C:\my\forums\so\081> cl printf.cpp /Feb
printf.cpp
printf.cpp(14): fatal error C1001: An internal error has occurred in the compiler.
(compiler file 'f:\dd\vctools\compiler\cxxfe\sl\p1\cxx\dymto.c', line 6771)
To work around this problem, try simplifying or changing the program near the locations listed above.
Please choose the Technical Support command on the Visual C++
Help menu, or open the Technical Support help file for more information
C:\my\forums\so\081> g++ printf.cpp
printf.cpp: In function 'int main()':
printf.cpp:14:43: error: no matching function for call to 'format_for(int, int, int)'
printf( "'%s'\n", format_for( 5, 2, 1 ) );
^
printf.cpp:4:6: note: candidate: template<class ... Args> const char* format_for(Args ..., int)
auto format_for( Args... args, int last_arg )
^
printf.cpp:4:6: note: template argument deduction/substitution failed:
printf.cpp:14:43: note: candidate expects 1 argument, 3 provided
printf( "'%s'\n", format_for( 5, 2, 1 ) );
^
C:\my\forums\so\081> _
所以,
为什么以上不能用g ++编译?
如何表达意图(希望从代码中显而易见)?
更一般地说,匹配调用可变参数模板函数的规则是什么?
Args出现在非推断的上下文中.在这种情况下,这使得它被推断为空包.
如果要提取最后一个参数但保留通常的演绎规则,可以编写一个简单的帮助器:
template <typename U>
constexpr U&& last(U&& u) {return std::forward<U>(u);}
template <typename U, typename... T>
constexpr decltype(auto) last(U&&, T&&... t) {return last(std::forward<T>(t)...);}
Run Code Online (Sandbox Code Playgroud)
演示.
更一般地说,匹配调用可变参数模板函数的规则是什么?
这些都非常冗长,但是没有尾随的函数参数包通常会被推导为空的或产生演绎失败.
在您的特定情况下,尝试index_sequences:
template <class... Args, std::size_t... indices>
auto format_for( std::index_sequence<indices...>, Args... args )
{
auto tup = std::forward_as_tuple(std::forward<Args>(args)...);
using Specifier = char const [3];
static Specifier const s[] = { {'%', (char)('f'+(0*std::get<indices>(tup))), ' '}..., {'%', 'f', 0} };
int last_arg = std::get<sizeof...(Args)-1>(tup);
return s;
}
template <class... Args>
auto format_for( Args&&... args ) {
return format_for(std::make_index_sequence<sizeof...(Args)-1>{},
std::forward<Args>(args)...);
}
Run Code Online (Sandbox Code Playgroud)
...并希望编译器能够很好地优化 - Demo 2.或沿着厚颜无耻的道路走下去:
template <class... Args, std::size_t... indices>
auto format_for( std::index_sequence<indices...>, Args... args )
{
using Specifier = char const [3];
static Specifier const s[] = {
{'%', (char)(indices == sizeof...(Args)-1?
'f' : 'f'+(0*args)), ' '}... };
int last_arg = last(args...); // As before
return s;
}
template <class... Args>
auto format_for( Args&&... args ) {
return format_for(std::make_index_sequence<sizeof...(Args)>{},
std::forward<Args>(args)...);
}
Run Code Online (Sandbox Code Playgroud)
演示3.