std::function const 函数的类型不完整
std::function incomplete type on const function
考虑以下按预期工作的代码:
#include <iostream>
#include <functional>
struct foo
{
std::function<int()> get;
};
struct bar
{
int get()
{
return 42;
}
};
int main()
{
foo f;
bar b;
f.get = std::bind(&bar::get, &b);
if (f.get())
std::cout << "f.get(): " << f.get() << std::endl;
return 0;
}
现在,假设 bar::get()
是一个 const 成员函数:
#include <iostream>
#include <functional>
struct foo
{
std::function<int()const> get;
};
struct bar
{
int get() const
{
return 42;
}
};
int main()
{
foo f;
bar b;
f.get = std::bind(&bar::get, &b);
if (f.get())
std::cout << "f.get(): " << f.get() << std::endl;
}
使用 GCC 9.2,此片段会引发以下编译器错误:
main.cpp:6:31: error: field 'get' has incomplete type 'std::function<int() const>'
6 | std::function<int()const> get;
| ^~~
In file included from /usr/local/include/c++/9.2.0/functional:59,
from main.cpp:2:
/usr/local/include/c++/9.2.0/bits/std_function.h:128:11: note: declaration of 'class std::function<int() const>'
128 | class function;
| ^~~~~~~~
我不明白为什么 foo::get
的类型不完整。
有人可以指出我理解这种行为的正确方向并相应地 "fixing" 吗?
我需要绑定一个 const 成员函数到一个函数指针。
只需使用 std::function<int()>
.
const
位只对成员函数有意义。您已经将 bar::get
绑定到实例 b
以将其保存为 std::function
.
std::bind
不会通过 const
ness 传递给可调用对象。因此,以下将起作用:
struct foo {
std::function<int()> get;
// ^ note there is no 'const'
};
如@KamilCuk 所述:
The constness is checked at std::bind, not at std::function
您不需要将 explicit
const 传递给 std::function
。只需使用您的旧原型:std::function<int()>
。如果您没有 const 重载(这意味着您有 int bar::get()
或 int bar::get() const
之一)相同的成员函数(否则,您需要显式类型转换),它将起作用。
实际上,您的函数 (int bar::get() const
) 将具有这样的签名(在幕后):
// int bar::get() const
int get(const bar *const this)
{
return 42;
}
// int bar::get()
int get(bar *const this)
{
return 42;
}
如果你有重载并且想绑定特定的成员函数,你可以这样做:
typedef int(bar::*fptr)(void) const; // or remove const
std::bind((fptr)&bar::get, &b );
看到这个:
#include <iostream>
#include <functional>
#include <vector>
struct foo
{
std::function<int()> get;
};
struct bar
{
int get()
{
return 42;
}
int get() const
{
return 50;
}
};
int main()
{
foo f;
bar b;
typedef int (bar::*fptr)(void);
typedef int (bar::*fcptr)(void) const;
f.get = std::bind((fptr)&bar::get, &b);
if (f.get())
std::cout << "f.get(): " << f.get() << std::endl;
f.get = std::bind((fcptr)&bar::get, &b);
if (f.get())
std::cout << "f.get(): " << f.get() << std::endl;
}
输出:
f.get(): 42
f.get(): 50
int()const
是一个 abominable type。
std::function<int()const>
不是类型,因为它不匹配 only defined specialisation
namespace std {
template< class R, class... Args >
class function<R(Args...)> { ... };
}
考虑以下按预期工作的代码:
#include <iostream>
#include <functional>
struct foo
{
std::function<int()> get;
};
struct bar
{
int get()
{
return 42;
}
};
int main()
{
foo f;
bar b;
f.get = std::bind(&bar::get, &b);
if (f.get())
std::cout << "f.get(): " << f.get() << std::endl;
return 0;
}
现在,假设 bar::get()
是一个 const 成员函数:
#include <iostream>
#include <functional>
struct foo
{
std::function<int()const> get;
};
struct bar
{
int get() const
{
return 42;
}
};
int main()
{
foo f;
bar b;
f.get = std::bind(&bar::get, &b);
if (f.get())
std::cout << "f.get(): " << f.get() << std::endl;
}
使用 GCC 9.2,此片段会引发以下编译器错误:
main.cpp:6:31: error: field 'get' has incomplete type 'std::function<int() const>'
6 | std::function<int()const> get;
| ^~~
In file included from /usr/local/include/c++/9.2.0/functional:59,
from main.cpp:2:
/usr/local/include/c++/9.2.0/bits/std_function.h:128:11: note: declaration of 'class std::function<int() const>'
128 | class function;
| ^~~~~~~~
我不明白为什么 foo::get
的类型不完整。
有人可以指出我理解这种行为的正确方向并相应地 "fixing" 吗?
我需要绑定一个 const 成员函数到一个函数指针。
只需使用 std::function<int()>
.
const
位只对成员函数有意义。您已经将 bar::get
绑定到实例 b
以将其保存为 std::function
.
std::bind
不会通过 const
ness 传递给可调用对象。因此,以下将起作用:
struct foo {
std::function<int()> get;
// ^ note there is no 'const'
};
如@KamilCuk 所述:
The constness is checked at std::bind, not at std::function
您不需要将 explicit
const 传递给 std::function
。只需使用您的旧原型:std::function<int()>
。如果您没有 const 重载(这意味着您有 int bar::get()
或 int bar::get() const
之一)相同的成员函数(否则,您需要显式类型转换),它将起作用。
实际上,您的函数 (int bar::get() const
) 将具有这样的签名(在幕后):
// int bar::get() const
int get(const bar *const this)
{
return 42;
}
// int bar::get()
int get(bar *const this)
{
return 42;
}
如果你有重载并且想绑定特定的成员函数,你可以这样做:
typedef int(bar::*fptr)(void) const; // or remove const
std::bind((fptr)&bar::get, &b );
看到这个:
#include <iostream>
#include <functional>
#include <vector>
struct foo
{
std::function<int()> get;
};
struct bar
{
int get()
{
return 42;
}
int get() const
{
return 50;
}
};
int main()
{
foo f;
bar b;
typedef int (bar::*fptr)(void);
typedef int (bar::*fcptr)(void) const;
f.get = std::bind((fptr)&bar::get, &b);
if (f.get())
std::cout << "f.get(): " << f.get() << std::endl;
f.get = std::bind((fcptr)&bar::get, &b);
if (f.get())
std::cout << "f.get(): " << f.get() << std::endl;
}
输出:
f.get(): 42
f.get(): 50
int()const
是一个 abominable type。
std::function<int()const>
不是类型,因为它不匹配 only defined specialisation
namespace std {
template< class R, class... Args >
class function<R(Args...)> { ... };
}