在Fedora 11上编译一些工作代码时,我收到此错误:
/usr/include/c++/4.4.1/cstdarg:56: error: ‘::va_list’ has not been declared
Run Code Online (Sandbox Code Playgroud)
我在用:
[doriad@davedesktop VTK]$ g++ --version
g++ (GCC) 4.4.1 20090725 (Red Hat 4.4.1-2)
Run Code Online (Sandbox Code Playgroud)
有谁知道是什么问题?
看到这段代码的输出我感到很惊讶:
public class File
{
public static void main(String[] args)
{
movie();
}
static void movie(double... x)
{
System.out.println("No varargs");
}
static void movie(int... x)
{
System.out.println("One argument");
}
}
Run Code Online (Sandbox Code Playgroud)
它输出,
One argument
Run Code Online (Sandbox Code Playgroud)
为什么会这样?
我认为这段代码不能编译,因为调用movie()是模糊的,但运行正常并输出One argument.
如果我将代码修改为:
public class File
{
public static void main(String[] args)
{
movie();
}
static void movie(boolean... x) //Changed the parameter type to boolean from double
{
System.out.println("No varargs");
}
static void movie(int... x)
{
System.out.println("One argument");
}
} …Run Code Online (Sandbox Code Playgroud) 使用varargs时,结果数组的组件类型是如何确定的?
例如,该程序是否保证打印true或在技术上未指定其行为?
public static void main(String[] args) {
foo("", 0);
}
static <T> void foo(T... arr) {
System.out.println(arr.getClass() == Serializable[].class);
}
Run Code Online (Sandbox Code Playgroud) 在代码审查/clang-tidy 运行时,我遇到了一个具有如下签名的函数:
void appendFoo(const char * fmt, va_list& rVaList);
Run Code Online (Sandbox Code Playgroud)
我以前从未见过这个。Afaik,您可以va_list按值传递(也可以通过指针传递?)。
这引出了我的第一个问题:通过va_list引用传递合法吗?它是否按预期工作?
不管怎样,appendFoo()调用vsprintf()它的定义和 clang-tidy 给出了以下警告:Function 'vsprintf' is called with an uninitialized va_list argument [clang-analyzer-valist.Uninitialized]。看起来的定义appendFoo()基本上是这样的:
void appendFoo(const char * fmt, va_list& rVaList) {
// retracted: allocate buffer
vsprintf(buffer, fmt, rVaList);
// errorhandling
// de-allocate buffer
}
Run Code Online (Sandbox Code Playgroud)
(是的, 的返回值vsprintf被忽略,错误以另一种方式“处理”。我正在修复它......)
特别是,不va_copy调用va_start、 等。
删除引用va_list并按值传递,即将签名更改为void appendFoo(const char * fmt, va_list rVaList);,消除了 clang-tidy 警告。 …
给定具有可变参数模板构造函数的类型将参数转发给实现类,是否可以限制使用SFINAE转发的类型?
首先,考虑带有通用引用的构造函数的非变量情形.这里可以禁止通过SFINAE转发非常量左值引用来代替使用复制构造函数.
struct foo
{
foo() = default;
foo(foo const&)
{
std::cout << "copy" << std::endl;
}
template <
typename T,
typename Dummy = typename std::enable_if<
!std::is_same<
T,
typename std::add_lvalue_reference<foo>::type
>::value
>::type
>
foo(T&& x)
: impl(std::forward<T>(x))
{
std::cout << "uref" << std::endl;
}
foo_impl impl;
};
Run Code Online (Sandbox Code Playgroud)
这种通用引用的限制很有用,因为否则实现类将接收类型的非const左值引用foo,它不知道.LWS的完整示例.
但是,如何使用可变参数模板?有可能吗?如果是这样,怎么样?天真的扩展不起作用:
template <
typename... Args,
typename Dummy = typename std::enable_if<
!std::is_same<
Args...,
typename std::add_lvalue_reference<foo>::type
>::value
>::type
>
foo(Args&&... args)
: impl(std::forward<Args>(args)...)
{
std::cout << "uref" …Run Code Online (Sandbox Code Playgroud) 示例代码是:
#include <unordered_map>
int main() {
std::unordered_map<int, std::pair<int, int>> map;
map.emplace(1, {1, 1});
return 0;
}
Run Code Online (Sandbox Code Playgroud)
哪里emplace()有签名,如:
template <class... _Args>
pair<iterator, bool> emplace(_Args&&... __args);
Run Code Online (Sandbox Code Playgroud)
该gcc说的功能expectes 0参数- 2提供的.该clang说,函数需要1个参数- 2提供的.
我甚至不明白 - 这段代码有什么问题?
c++ variadic-functions compiler-bug c++11 list-initialization
题
有人可以解释这些论证类型之间的差异吗?此外,如果可能的话,请使用代码提供适当的用例(价值1000字).
Nota bene
如果需要更多信息,请在评论中告诉我.
背景
我试图理解以下结构之间的任何差异,并理解适当的用例(如果有的话,有示例).我搜索过SO,Google等人.(blogosphere)没有找到满意的答案.
在编写数据存储对象时,我遇到了NSPredicate的以下初始化器:

Swift头文件(1.2)注意到:

博客评论表明Objective-C中va_list的以下用法
+ (void) log:(NSString *) format arguments:(va_list) argList
{
[self logString: [NSString stringWithFormat: format arguments:
argList]];
}
+ (void) log:(NSString *) format, ...
{
va_list argList;
va_start(argList, format);
{
[self log: format arguments: argList];
}
va_end(argList);
}
Run Code Online (Sandbox Code Playgroud)
CVarArgType是一种协议,可以根据Swift头文件使用如下.

在我的自定义类中,我有以下用例:
/* Finds an array of entity in the MOC if any exists using an optional
* predicate with an array of arguments
*
* Usage:
* eg. var items = CustomEntity.findInStore(dbStore, predicate: …Run Code Online (Sandbox Code Playgroud) C#/ .NET通过传递Array类型by-reference来具有可变参数函数参数(与C/C++相反,它只是将所有值直接放在堆栈上,无论好坏).
在C#世界中,这有一个很好的优点,允许您使用'raw'参数或可重用的数组实例调用相同的函数:
CultureInfo c = CultureInfo.InvariantCulture;
String formatted0 = String.Format( c, "{0} {1} {2}", 1, 2, 3 );
Int32 third = 3;
String formatted0 = String.Format( c, "{0} {1} {2}", 1, 2, third );
Object[] values = new Object[] { 1, 2, 3 };
String formatted1 = String.Format( c, "{0} {1} {2}", values );
Run Code Online (Sandbox Code Playgroud)
这意味着生成的CIL相当于:
String formatted0 = String.Format( c, "{0} {1} {2}", new Object[] { 1, 2, 3 } );
Int32 third = 3;
String formatted0 …Run Code Online (Sandbox Code Playgroud) 我试图将一个基元数组(在我的例子中int[])传递给一个带有varargs的方法.
让我们说:
// prints: 1 2
System.out.println(String.format("%s %s", new String[] { "1", "2"}));
// fails with java.util.MissingFormatArgumentException: Format specifier '%s'
System.out.println(String.format("%s %s", new int[] { 1, 2 }));
Run Code Online (Sandbox Code Playgroud)
但请注意,第一行会收到以下警告:
类型String []的方法格式(String,Object ...)的最后一个参数与vararg参数类型不完全匹配.转换为Object []以确认非varargs调用,或者为varargs调用传递Object类型的各个参数.
另请注意,我不使用构造函数输入数组,但是我从封闭方法中获取它,其签名我无法更改,例如:
private String myFormat(int[] ints) {
// whatever format it is, it's just an example, assuming the number of ints
// is greater than the number of the format specifiers
return String.format("%s %s %s %s", ints);
}
Run Code Online (Sandbox Code Playgroud) 这个小程序
public class Client {
public static void main(String[] args) throws Exception {
Arrays.asList(null);
}
}
Run Code Online (Sandbox Code Playgroud)
抛出一个NullPointerException。
Exception in thread "main" java.lang.NullPointerException
at java.base/java.util.Objects.requireNonNull(Objects.java:221)
at java.base/java.util.Arrays$ArrayList.<init>(Arrays.java:4322)
at java.base/java.util.Arrays.asList(Arrays.java:4309)
at org.example.Client.main(Client.java:10)
Run Code Online (Sandbox Code Playgroud)
但是,该程序
public static void main(String[] args) throws Exception {
Arrays.asList(returnNull());
}
private static Object returnNull(){
return null;
}
Run Code Online (Sandbox Code Playgroud)
才不是。他们为什么表现不同?
java ×4
c++ ×3
c++11 ×2
.net ×1
arrays ×1
c# ×1
compiler-bug ×1
g++ ×1
gcc ×1
generics ×1
nspredicate ×1
objective-c ×1
overloading ×1
sfinae ×1
swift ×1