我在看“如何正确使用可变参数模板的引用”,并想知道逗号扩展可以走多远。
这是答案的一个变体:
inline void inc() { }
template<typename T,typename ...Args>
inline void inc(T& t, Args& ...args) { ++t; inc(args...); }
Run Code Online (Sandbox Code Playgroud)
由于可变参数被扩展到一逗号-分隔它们的元素的列表,是那些逗号语义上等同于模板/功能参数的分离器,或者他们插入词法,使得它们适用于任何(-预处理后)的使用,包括逗号操作符?
这适用于我的 GCC-4.6:
// Use the same zero-argument "inc"
template<typename T,typename ...Args>
inline void inc(T& t, Args& ...args) { ++t, inc(args...); }
Run Code Online (Sandbox Code Playgroud)
但是当我尝试时:
// Use the same zero-argument "inc"
template<typename T,typename ...Args>
inline void inc(T& t, Args& ...args) { ++t, ++args...; }
Run Code Online (Sandbox Code Playgroud)
我不断收到解析错误,期待“;” 在“...”之前,并且“args”不会扩展其包。为什么不起作用?是因为如果“args”为空,我们会得到一个无效的标点符号?合法吗,我的编译器不够好?
(我试过在括号中围绕“args”,和/或使用后增量;都没有奏效。)
我想将调用转发到具有可变方法的库.我能提出来复制问题的最简单的例子是:
void Bar(int useless, ...)
{
//Does something
}
template<typename... Args>
void Foo(int useless, Args... args)
{
Bar(useless, args...);
}
Run Code Online (Sandbox Code Playgroud)
如你所见,我已经去了.但是,即使这个编译,它似乎导致堆栈有一个摇摆,我看到应用程序退出时出错.从编译器的角度来看,我可以理解这个解决方案存在问题.
我不确定如何使这个工作,或者是否有可能让这个工作.我看到有些人建议在类似情况下使用"索引技巧",但我无法在这个特殊场合使用它.
任何帮助赞赏!
在以下代码中:
#include <iostream>
struct Base {
virtual ~Base() = default;
template <typename T, typename... Args> void helper (void (T::*)(Args..., int), Args...);
void bar (int n) {std::cout << "bar " << n << std::endl;}
};
struct Derived : Base {
void baz (double d, int n) {std::cout << "baz " << d << ' ' << n << std::endl;}
};
template <typename T, typename... Args>
void Base::helper (void (T::*f)(Args..., int), Args... args) {
// A bunch on lines here (hence the …Run Code Online (Sandbox Code Playgroud) 我想使用variadic模板构建一个哈希码队列.最小的示例代码是
template<typename T>
void hash_queue(queue<size_t>& q){
q.push( typeid(T).hash_code() );
}
template<typename T, typename... Ts>
void hash_queue(queue<size_t>& q){
hash_queue<Ts...>(q);
q.push( typeid(T).hash_code() );
}
int main(){
queue<size_t> q;
hash_queue<int, float, double>(q);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在编译我得到
main.cpp: In instantiation of ‘void hash_queue(std::queue<long unsigned int>&) [with T = float; Ts = {double}]’:
main.cpp:19:22: required from ‘void hash_queue(std::queue<long unsigned int>&) [with T = int; Ts = {float, double}]’
main.cpp:25:35: required from here
main.cpp:19:22: error: call of overloaded ‘hash_queue(std::queue<long unsigned int>&)’ is ambiguous
hash_queue<Ts...>(q);
^
main.cpp:19:22: …Run Code Online (Sandbox Code Playgroud) 除非我弄错了,否则Fortran无法用任意数量的参数编写函数或子例程(更简洁地称为可变参数函数).
例如:
RESULT = FUNC(A1, A2 [, A3 [, ...]])
我知道,我可以创建可选参数,但参数的数量是有限的,必须在函数定义中逐个手动声明.
那么Fortran编译器如何实现,MAX或者MIN实际上是
RESULT = MAX(A1, A2 [, A3 [, ...]])
特别令人困惑的是,这些可变参数MAX和MIN函数显然是Fortran 77标准的一部分.因此,实现这些功能的任何能力都必须在1977年左右提供.
我有一个模板类,必须在调用参数和返回类型为泛型的函数之前执行某些操作.
这是方法:
template <typename ReturnType, typename ...Args>
ReturnType function (Args ...args) {
// prepare for call
// ...
ReturnType rv = makeCall(args...); // [1]
// dismiss the call
// ...
return rv;
}
Run Code Online (Sandbox Code Playgroud)
当然,如果ReturnType没有正确编译它void.当我在这种情况下使用它时:
function<void>(firstArg, secondArg);
Run Code Online (Sandbox Code Playgroud)
编译器响应
error: return-statement with a value, in function returning 'void' [-fpermissive]
指向标有[1]的行.
除了传递-fpermissive给编译器之外还有其他解决方案吗?我宁愿有一个独特的方法,因为我发现可能的解决方案是使用enable_if和实例化不同的版本is_same.
先感谢您.
- 更新 -
这是一个完整的例子.我应该说我们的函数确实是类方法.
#include <type_traits>
#include <iostream>
class Caller {
public:
Caller() {}
template <typename ReturnType, typename ...Arguments>
ReturnType …Run Code Online (Sandbox Code Playgroud) 我使用名为 fmt 的格式化库(http://fmtlib.net/latest/)。
可能的用途之一是:
fmt::format("Hello, {name}! The answer is {number}. Goodbye, {name}.", fmt::arg("name", "World"), fmt::arg("number", 42));
Run Code Online (Sandbox Code Playgroud)
我想将此调用包装在一个函数中,我将其调用为:
myFunction(myString, {"name", "World"}, {"number", 42});
Run Code Online (Sandbox Code Playgroud)
对于任意数量的参数。
到目前为止,我只成功地完成了一个可使用成对列表调用的函数:
myFunction(myString, std::make_pair("name", "World"), std::make_pair("number", 42));
Run Code Online (Sandbox Code Playgroud)
具有以下功能:
std::string myFunction(const char* str, const Args&... rest) const
{
return fmt::format(mLocale.getPOILabel(label), fmt::arg(rest.first, rest.second)...);
}
Run Code Online (Sandbox Code Playgroud)
但我不想使用成对的。
我应该怎么办 ?
PS:fmt::arg不能在函数之间传递。
该类typing.Tuple可以与任意数量的类型参数一起使用,例如Tuple[int, str, MyClass]或Tuple[str, float]。我如何实现我自己的可以像这样使用的类?我了解如何继承typing.Generic. 下面的代码演示了这一点。
from typing import TypeVar, Generic
T = TypeVar("T")
class Thing(Generic[T]):
def __init__(self, value: T):
self.value = value
def f(thing: Thing[int]):
print(thing.value)
if __name__ == '__main__':
t = Thing("WTF")
f(t)
Run Code Online (Sandbox Code Playgroud)
t上面的代码可以工作,但是类型检查器(在我的例子中是 PyCharm)会捕获应该是类型Thing[int]而不是 的事实Thing[str]。这一切都很好,但是如何让该类Thing支持任意数量的类型参数,就像Tuple那样?
我正在使用很棒的fmt C++ 库来更优雅地格式化字符串。
我想将一个非变量参数列表传递给fmt::format. 它可能是一个std::vector, 或std::string或其他任何形式,但它始终与格式字符串匹配。
所以fmt::format工作原理如下:
std::string message = fmt::format("The answer is {} so don't {}", "42", "PANIC!");
Run Code Online (Sandbox Code Playgroud)
但我想要的是这样的:
std::vector<std::string> arr;
arr.push_back("42");
arr.push_back("PANIC!");
std::string message = fmt::format("The answer is {} so don't {}", arr);
Run Code Online (Sandbox Code Playgroud)
有没有办法/解决方法来做到这一点?
如何获取参数包的前n个元素?或者最后 n 个元素,或者 [n, n+1, ..., m) 中的一片元素?例如:
head<3>(1, 2.0f, "three", '4') => make_tuple(1, 2.0f, "three")
tail<2>(1, 2.0f, "three", '4') => make_tuple("three", '4')
slice<1,3>(1, 2.0f, "three", '4') => make_tuple(2.0, "three")
Run Code Online (Sandbox Code Playgroud)
这可以通过 std::tuple、std::integer_sequence 和 std::get 的组合来实现,但我想知道是否有更简单的方法。