相关疑难解决方法(0)

什么是"表达SFINAE"?

http://blogs.msdn.com/b/vcblog/archive/2011/09/12/10209291.aspx上,VC++团队正式声明他们尚未实现C++ 11核心功能"Expression SFINAE".但是,从http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2634.html复制的以下代码示例将被VC++编译器接受.

例1:

template <int I> struct A {};

char xxx(int);
char xxx(float);

template <class T> A<sizeof(xxx((T)0))> f(T){}

int main()
{
    f(1);
}
Run Code Online (Sandbox Code Playgroud)

例2:

struct X {};
struct Y 
{
    Y(X){}
};

template <class T> auto f(T t1, T t2) -> decltype(t1 + t2); // #1
X f(Y, Y);  // #2

X x1, x2;
X x3 = f(x1, x2);  // deduction fails on #1 (cannot add X+X), calls #2
Run Code Online (Sandbox Code Playgroud)

我的问题是:什么是"表达SFINAE"?

c++ templates sfinae visual-c++ c++11

56
推荐指数
1
解决办法
1万
查看次数

在标准下调用std :: function <void(Args ...)>是违法的吗?

所有报价均来自N3797.

4/3 [转]

当且仅当声明T t = e时,表达式e可以隐式转换为类型T. 对于一些发明的临时变量t而言,其形式良好

这意味着没有表达式可以隐式转换为void,这void t=e对所有表达式都是非法的e.如果e是类型的表达式void,例如,这甚至是真的void(3).

所以类型的表达式void不能隐式转换为void.

这导致我们:

20.9.2/2要求[func.require]

将INVOKE(f,t1,t2,...,tN,R)定义为隐式转换为R的INVOKE(f,t1,t2,...,tN).

总之,INVOKE(f, t1, t2, ..., tN, R)当是永远有效Rvoid,如无(含void)可以隐式转换为void.

因此,所有都std::function<void(Args...)>具有属性!*this,因此不能被调用,因为唯一没有!*this后置条件的构造函数(或者不从function相同类型的另一个复制此类状态)需要Callable其中一个参数.

20.9.11.2/7类模板函数[func.wrap.func]

要求:F应为CopyConstructible.对于参数类型ArgTypes,f应为Callable(20.9.11.2)并返回R类型.A的拷贝构造函数和析构函数不应抛出异常.

20.9.11.2/2类模板函数[func.wrap.func]

类型F的可调用对象f对于参数类型ArgTypes是Callable,如果表达式INVOKE(f,declval()...,R)被认为是未评估的操作数(第5条),则返回类型R( 20.9.2).

如上所述,没有Callable表达std::function<void(Args...)>.

如果以某种方式std::function<void(Args...)>找到这样的地方,调用operator()将会形成错误:

调用[func.wrap.func.inv]

效果:INVOKE(f,std :: forward(args)...,R)(20.9.2),其中f是*this的目标对象(20.9.1).

因为INVOKE(f, …

c++ language-lawyer c++11 std-function c++14

27
推荐指数
1
解决办法
863
查看次数

使用`std :: function <void(...)>`来调用非void函数

前一段时间我用std::function的很像:

std::function<void(int)> func = [](int i) -> int { return i; };
Run Code Online (Sandbox Code Playgroud)

基本上,我这样做是因为我想在a中存储不同的函数对象std::function,但我不想限制这些函数的返回类型.由于这似乎有效,我接受了它.但我不相信它是安全的,我也无法找到任何文件.有谁知道这种用法是否合法?或者更一般地说,对象的规则是什么,可以安全地分配给std::function

编辑

为了澄清,我关心的问题是lambda函数返回一个int,而func声明返回类型void.我不确定这是否正常,特别是一旦打电话func().

c++ return-type c++11 std-function

19
推荐指数
1
解决办法
6574
查看次数

C++ std :: function找不到正确的重载

考虑以下情况:

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.是否有工作或其他方法来实现类似的东西.我不能使用模板,因为这些函数存储起来供以后使用,因为在这种情况下我无法确定参数的数量.如果你问我可以提交更多细节.

c++ lambda c++11

14
推荐指数
1
解决办法
2321
查看次数

重载std :: function参数以匹配lambda

可能重复:
消除对带有std :: functions的函数的调用
不是它的类型的std :: function部分的模板参数(签名)?

我想重载一个函数,以便可以使用各种不同的lambda(通常带有更多或更少的参数)来调用它.我试过的显而易见的事情是:

#include <functional>
#include <iostream>

extern void fn(std::function<void(int)>);
extern void fn(std::function<void(int, int)>);

void test()
{
    fn([](int a) { std::cout << "lambda with 1 arg " << a << std::endl; });
}
Run Code Online (Sandbox Code Playgroud)

但是,这与g ++(试过v4.6.2和v4.7.1)失败并出现错误:

test.cc: In function ‘void test()’:
test.cc:9:74: error: call of overloaded ‘fn(test()::<lambda(int)>)’ is ambiguous
test.cc:9:74: note: candidates are:
test.cc:4:13: note: void fn(std::function<void(int)>)
test.cc:5:13: note: void fn(std::function<void(int, int)>)
Run Code Online (Sandbox Code Playgroud)

现在我在这里这里找到了另一种(也就是更复杂的)方法,但我的问题是,为什么上面的代码失败了?标准中是否有某些内容表明它无法正常工作,或者这仅仅是g ++的错误/限制?

c++ lambda g++ c++11

11
推荐指数
1
解决办法
1382
查看次数

使用std :: function进行隐式转换

可能重复:
为什么我的C++编译器不能推导出boost函数的模板参数?
std :: function的模板参数(签名)是不是它的类型?

我有以下内容:

#include <functional>

void Foo( std::function<void()>    );
void Foo( std::function<void(int)> );
void Bar();

int main()
{
  Foo( Bar );     // Error: ambiguous
  Foo( [](){} );  // Error: ambiguous

  Foo( std::function<void()>( Bar    ) ); // Ok
  Foo( std::function<void()>( [](){} ) ); // Ok
}
Run Code Online (Sandbox Code Playgroud)

我可以在main()中使用前两行而不使用最后两行中的函数样式转换吗?也许使用std :: enable_if解决方案?

c++ overloading implicit-conversion c++11

7
推荐指数
1
解决办法
3538
查看次数

将lambda分配给std :: function

当推断的返回类型是std :: nullptr_t时,为什么允许第二个赋值?使用函数指针,这是禁止的.

为什么第二个lambda不运行?

#include <cstdio>
#include <functional>

int main()
{
    std::function<void* ()> f;

    f = []() -> void* {
        printf ("runs\n");
        return nullptr;
    };
    f();

    f = []() {
        printf ("doesn't run\n");
        return nullptr; // -> std::nullptr_t
    };
    f();

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

c++ lambda implicit-conversion c++11 std-function

7
推荐指数
1
解决办法
6755
查看次数

std :: function的copy-constructor是否要求模板类型的参数类型为完整类型?

鉴于:

#include <functional>
class world_building_gun;
class tile_bounding_box;
typedef std::function<void (world_building_gun, tile_bounding_box)> worldgen_function_t;
void foo() {
    worldgen_function_t v;
    worldgen_function_t w(v);
}
Run Code Online (Sandbox Code Playgroud)

这会编译吗?我的编译器说:

是的:GCC/stdlibc ++(在GCC和Clang中也是boost :: function都是)

No:Clang/libc ++(http://libcxx.llvm.org/,Clang 3.0,libc ++ SVN截至今日)

(如果"no"是正确答案,我将修复我的真实代码,将完整类型放入更多标题或使用boost :: function.)

编辑:这是Clang错误消息:

In file included from foo.cpp:2:
In file included from /usr/include/c++/v1/functional:462:
/usr/include/c++/v1/type_traits:2766:19: error: invalid appli
    static_assert(sizeof(_Tp) > 0, "Type must be complete.");
                  ^~~~~~~~~~~
/usr/include/c++/v1/type_traits:2752:15: note: in instantiation of template class 'std::__1::__check_complete<world_buildin
    : private __check_complete<_Hp>,
              ^
/usr/include/c++/v1/type_traits:2753:15: note: in instantiation of template class 'std::__1::__check_complete<world_buildin
      private __check_complete<_T0, _Tp...> …
Run Code Online (Sandbox Code Playgroud)

c++ boost tr1 c++11

6
推荐指数
1
解决办法
1633
查看次数

如何在C++中重载std :: function签名

我知道这个问题之前已被问过,但尽管我是一位经验丰富的编码员,但我不理解答案,也没有办法回答这些先前的问题,要求澄清.没有"回复"链接或任何东西.此外,这些问题还很旧.所以,我重新问这个问题.

我有一个类,我正在重载+ =运算符.我想要一个重载来获取一个裸函数指针,另一个需要一个std :: function:

void operator+=(void (*handler)());
void operator+=(function<void (void *, T)> handler);
Run Code Online (Sandbox Code Playgroud)

用法:

MyClass a;
a += [](){ DoSomething(); };
a += [](void *x, T y){ DoSomething(); };
Run Code Online (Sandbox Code Playgroud)

遗憾的是,代码无法编译,因为编译器无法确定第二个重载是否不适合第一个+ =调用.

如何定义我的operator + =成员函数来纠正这个问题?我不想改变运算符的使用方式(例如通过使用显式转换).我希望他们像上面所说的那样工作.

此外,还有以下过载也很方便:

void operator+=(function<void()> handler);
Run Code Online (Sandbox Code Playgroud)

但同样,我不能基于函数<>模板的签名重载.

有关更多示例,请参阅此主题:std :: function的模板参数(签名)是否是其类型的一部分? (我尝试实现该线程中提到的各种解决方案,但没有一个会编译)

我已经用多种语言编程了很多年,但我的C++技能有点生疏.

c++ lambda overloading signature

6
推荐指数
1
解决办法
1455
查看次数

为什么不起作用阻止不同返回类型的施工?

std::function 允许你这样做:

std::function<void()> = []()->int{return 42;};
Run Code Online (Sandbox Code Playgroud)

但不是这个:

std::function<void()> = [](int i)->int{return 42;};
Run Code Online (Sandbox Code Playgroud)

大概是因为返回类型不是函数签名的一部分.但是std::function是一个类类型,它被赋予一个返回类型,并且知道它构造的函数对象的返回类型.所以这里可能存在编译器错误.

为什么没有编译器错误?

c++

5
推荐指数
1
解决办法
93
查看次数

可变参数函数中可变参数模板类的隐式转换

考虑以下代码

#include <functional>
template<class ResultType, class ... Args>
void Foo( std::function<ResultType(Args...)> ) {}

void Dummy(int) {}

int main()
{
     Foo<void, int> ( std::function<void(int)>( Dummy ) ); // OK, no deduction and no conversion
     Foo( std::function<void(int)>( Dummy ) ); // OK, template argument deduction
     Foo<void, int>( Dummy ); // Compile error
}
Run Code Online (Sandbox Code Playgroud)

在第三个中,我知道不能进行模板推导,这就是明确指定模板参数的原因。但是为什么没有从void (*)(int)to的显式转换std::function<void(int)>

我查找了答案,但这些是关于模棱两可的重载解决方案或模板推论,而不是相关主题。

std::function 的模板参数(签名)不是其类型的一部分吗?

使用 std::function 进行模板类型推导

使用 std::function 进行隐式转换

然后我尝试使用我自己的模板类而不是 std::function 进行测试。

// Variadic template class
template<class ... T>
class Bar
{ …
Run Code Online (Sandbox Code Playgroud)

c++ templates variadic-functions implicit-conversion variadic-templates

5
推荐指数
1
解决办法
169
查看次数