我编写了一个traits类,它允许我在C++ 0x中提取有关函数或函数对象的参数和类型的信息(使用gcc 4.5.0测试).一般情况处理函数对象:
template <typename F>
struct function_traits {
template <typename R, typename... A>
struct _internal { };
template <typename R, typename... A>
struct _internal<R (F::*)(A...)> {
// ...
};
typedef typename _internal<decltype(&F::operator())>::<<nested types go here>>;
};
Run Code Online (Sandbox Code Playgroud)
然后我对全局范围内的普通函数进行了专门化:
template <typename R, typename... A>
struct function_traits<R (*)(A...)> {
// ...
};
Run Code Online (Sandbox Code Playgroud)
这工作正常,我可以将一个函数传递给模板或函数对象,它可以正常工作:
template <typename F>
void foo(F f) {
typename function_traits<F>::whatever ...;
}
int f(int x) { ... }
foo(f);
Run Code Online (Sandbox Code Playgroud)
如果foo我不想传递一个函数或函数对象,而是想传递一个lambda表达式,该怎么办?
foo([](int x) { ... });
Run Code Online (Sandbox Code Playgroud)
这里的问题是既不function_traits<>适用专业化.C++ …
考虑以下情况:
void Set(const std::function<void(int)> &fn);
void Set(const std::function<void(int, int)> &fn);
Run Code Online (Sandbox Code Playgroud)
现在调用函数
Set([](int a) {
//...
});
Run Code Online (Sandbox Code Playgroud)
给"重载函数的模糊调用"错误.我正在使用Visual Studio 2010.是否有工作或其他方法来实现类似的东西.我不能使用模板,因为这些函数存储起来供以后使用,因为在这种情况下我无法确定参数的数量.如果你问我可以提交更多细节.
我不确定是否可能,所以这就是我想要找到的.
我想创建一个接受任何类型的函子/可调用对象的函数,但我想知道参数类型是什么.(但不强制执行)
所以,这个捕获所有但不给我参数的类型:
template < typename T >
void optionA( T );
Run Code Online (Sandbox Code Playgroud)
这个捕获最多,并具有参数的类型
template < typename T >
void optionB( std::function< void(T) > );
Run Code Online (Sandbox Code Playgroud)
但是这个不允许lambdas,所以
optionB( [](int){} );
Run Code Online (Sandbox Code Playgroud)
不会编译.这有点奇怪,因为这将编译:
std::function< void(int) > func = [](int){};
optionB( func );
Run Code Online (Sandbox Code Playgroud)
那么有没有办法接受所有选项,还知道期望哪种类型的参数?
提前致谢!
- 编辑 -
我想这样做的原因是我想让我的库用户注册一个特定类型的回调.对我来说,最自然的方式是
auto callback = []( int val ) { cout << "my callback " << val << endl; };
object.register( callback );
Run Code Online (Sandbox Code Playgroud)
(使用或不使用回调作为中间变量)
由于我需要根据用户期望的值类型修改行为,我需要知道他/她期望的类型.
我想提取函数的返回类型.问题是,还有其他函数具有相同的名称但签名不同,我无法让C++选择合适的函数.我知道std :: result_of,但是从几次尝试我得出结论它也遇到了同样的问题.我也听说过涉及decltype的解决方案,但我不知道具体细节.
目前我正在使用模板元编程从函数指针类型中提取返回类型,这对于有限数量的参数(任何非限制解决方案?)都可以正常工作,因为函数指针类型的提取适用于明确的函数.
#include <iostream>
using namespace std;
// ----
#define resultof(x) typename ResultOf<typeof(x)>::Type // might need a & before x
template <class T>
class ResultOf
{
public:
typedef void Type; // might need to be T instead of void; see below
};
template <class R>
class ResultOf<R (*) ()>
{
public:
typedef R Type;
};
template <class R, class P>
class ResultOf<R (*) (P)>
{
public:
typedef R Type;
};
// ----
class NoDefaultConstructor
{
public:
NoDefaultConstructor (int) …Run Code Online (Sandbox Code Playgroud) 如何获得用作模板参数的任意函数类型的arity?
该函数可以是普通函数,lambda或函子.例:
template<typename TFunc>
std::size_t getArity()
{
// ...?
}
template<typename TFunc>
void printArity(TFunc mFunc)
{
std::cout << "arity: " << getArity<TFunc>() << std::endl;
}
void testFunc(int) { }
int main()
{
printArity([](){}); // prints 0
printArity([&](int x, float y){}); // prints 2
printArity(testFunc); // prints 1
}
Run Code Online (Sandbox Code Playgroud)
我可以访问所有C++ 14功能.
我是否必须为每种函数类型(以及所有相应的限定符)创建特化?或者有更简单的方法吗?
我需要一种方法来计算函数的参数类型,所以我编写了一个closure_traits类,如下所示,受到启发是否有可能找出lambda的参数类型和返回类型?.
但是,当我尝试将它应用于一个简单的lambda时,我得到'operator()'不是'(lambda type)'的成员的错误.但是,根据cppreference,lambda确实有一个operator().我也尝试过使用std :: function,并得到了相同的错误.我想我不确定出了什么问题,任何帮助都会非常感激.
#include<type_traits>
#include<tuple>
#include<utility>
#include<iostream>
/* For generic types use the type signature of their operator() */
template <typename T>
struct closure_traits : public
closure_traits<decltype(&T::operator())> {};
/* Otherwise, we do a template match on a function type. */
template <typename ClassType, typename ReturnType,
typename... ArgTypes>
struct closure_traits<ReturnType (ClassType::*) (ArgTypes... args)>
{
using arity = std::integral_constant<std::size_t,
sizeof...(ArgTypes)>;
using Ret = ReturnType;
/* The argument types will be the same as the types of the
* …Run Code Online (Sandbox Code Playgroud) (这里的根本问题是我正在尝试使用decltype或者某些其他类型的演绎可能基于auto涉及lambdas的复杂表达式.我正在尝试找到某种解决方法.我一直在玩http: //pfultz2.github.com/Pythy/ for polymorphic lambdas.如果没有告诉你一个长篇故事,我就无法充分发挥其动力!)
我希望能够decltype([](int){return 3.5L};获得lambda的类型,或者至少返回类型.是的,我知道lambdas有一个独特的类型,我不需要提醒,decltype([](int){return 3.5L};如果在两个不同的行上使用它将提供两种不同的类型.
如果我decltype在lambda上使用,那么我会得到一条错误消息('lambda在未评估的上下文中使用').我知道这似乎是一个合理的错误信息,但我很惊讶C++握着那样的手!允许这样做是有用的,特别是访问lambda的返回类型.这个错误只是过度出错的错误消息的结果,还是真的有一个很好的理由为什么它不能完成?
像这样的表达式在成员函数内部起作用:
template<typename T>
struct X {
void foo() {
static auto l = [](int){return 3.5;};
}
};
Run Code Online (Sandbox Code Playgroud)
但我不允许这样做:
template<typename T>
struct X {
static auto var = [](int){return 3.5;}; // will also fail if I use constexpr here
};
x.cpp:8:47: error: expression ‘#‘lambda_expr’ not supported by
dump_expr#<expression error>’ is not a constant-expression
x.cpp:8:47: error: unable to deduce ‘const auto’ from …Run Code Online (Sandbox Code Playgroud) 我最近得知我不能:
但我最近也了解到我可以 调用decltype以获取所述函数的返回类型
所以一个未定义的函数:
int foo(char, short);
Run Code Online (Sandbox Code Playgroud)
我想知道是否有一种方法可以将参数类型与a中的类型相匹配tuple.这显然是一个元编程问题.我真正拍摄的是decltypeargs这个例子中的东西:
enable_if_t<is_same_v<tuple<char, short>, decltypeargs<foo>>, int> bar;
Run Code Online (Sandbox Code Playgroud)
任何人都可以帮助我了解如何decltypeargs制作?
我有一个使用返回码的类:
class MyClass
{
// ...
public:
// ValueType get_value() const; // usual code
ErrorCode get_value(ValueType& value) const; // uses error code
// ...
};
Run Code Online (Sandbox Code Playgroud)
因此,第二种形式get_value()实际上将值作为函数参数提供,而不是作为返回值.
是否有可能推断出函数参数的类型get_value(),也许使用 decltype?
int main()
{
// ...
MyClass my_class;
// auto val = my_class.get_value(); // okay: value has correct type
declytype( /* something here */ ) value;
const auto error = my_class.get_value( value );
// ...
}
Run Code Online (Sandbox Code Playgroud) 我一直在努力解决编译问题,并且能够将问题缩小到一个小代码段.
为了设置阶段,我正在尝试执行CRTP,其中基本方法在派生类中调用另一个.复杂的是,我想使用尾随返回类型直接获取转发类型到Derived类的方法.除非我转发到派生类中的调用运算符,否则总是无法编译.
这编译:
#include <utility>
struct Incomplete;
template <typename Blah>
struct Base
{
template <typename... Args>
auto entry(Args&&... args)
-> decltype(std::declval<Blah&>()(std::declval<Args&&>()...));
};
void example()
{
Base<Incomplete> derived;
}
Run Code Online (Sandbox Code Playgroud)
虽然这不是:(注意唯一区别的评论)
#include <utility>
struct Incomplete;
template <typename Blah>
struct Base
{
template <typename... Args>
auto entry(Args&&... args)
-> decltype(std::declval<Blah&>().operator()(std::declval<Args&&>()...));
// I only added this ^^^^^^^^^^^
};
void example()
{
Base<Incomplete> derived;
}
Run Code Online (Sandbox Code Playgroud)
我得到的错误:
<source>: In instantiation of 'struct Base<Incomplete>':
15 : <source>:15:22: required from here
10 : <source>:10:58: …Run Code Online (Sandbox Code Playgroud) c++ templates operator-overloading language-lawyer name-lookup
c++ ×10
c++11 ×6
lambda ×5
templates ×5
c++14 ×2
decltype ×2
addressof ×1
arity ×1
function ×1
functor ×1
name-lookup ×1
overloading ×1
return-value ×1