具有默认 std::function 参数的模板函数导致符号 [...] 已经定义
Templated function with defaulted std::function parameter causes symbol [...] already defined
我只是 运行 有点奇怪。
不知道是不是BUG,如果不是的话希望有人能解释一下。
我的问题是,当我创建一个将 std::function
作为默认参数的模板化函数时,我只能创建该函数的一个模板实例,否则会出现错误。
考虑以下代码:
#include <functional>
template<bool B>
void wut(std::function<void()> f = []() {})
{
f();
}
int main() {
wut<false>(); // works
wut<false>(); // still works
wut<true>(); // error
return 0;
}
编译此代码时出现以下错误:
{standard input}: Assembler messages:
{standard input}:28: Error: symbol `_ZNSt14_Function_base13_Base_managerIUlvE_E10_M_managerERSt9_Any_dataRKS3_St18_Manager_operation' is already defined
{standard input}:127: Error: symbol `_ZNSt17_Function_handlerIFbvEUlvE_E9_M_invokeERKSt9_Any_data' is already defined
这是一个 gcc 错误(在 7.3 版后看起来已修复)我们可以通过查看部分 [expr.prim.lambda.capture]p9:
来了解这一点
A lambda-expression appearing in a default argument shall not
implicitly or explicitly capture any entity. [Example:
void f2() {
int i = 1;
void g1(int = ([i]{ return i; })()); // ill-formed
void g2(int = ([i]{ return 0; })()); // ill-formed
void g3(int = ([=]{ return i; })()); // ill-formed
void g4(int = ([=]{ return 0; })()); // OK
void g5(int = ([]{ return sizeof i; })()); // OK
}
—end example]
作为 IDEOne 的替代品,您可以使用与 gcc 和 clang 版本保持同步的 Wandbox,请参阅 your example live there。
看起来像是一个编译器错误。
然而,在头文件中使用 lambda 充满了 ODR 问题。所以我会避免它。
在c++17中:
template<auto X>
struct always_return {
template<class...Args>
auto operator()(Args&&...)const{ return X; }
};
template<bool B>
void wut(std::function<bool()> f = always_return<false>{})
{
或在c++11:
template<class T>
struct always_return_t {
T t;
template<class...Args>
auto operator()(Args&&...)const{ return t; }
};
template<class T>
always_return_t<typename std::decay<T>::type> always_return(T&&t) {
return {std::forward<T>(t)};
}
template<bool B>
void wut(std::function<bool()> f = always_return(false)){
我只是 运行 有点奇怪。 不知道是不是BUG,如果不是的话希望有人能解释一下。
我的问题是,当我创建一个将 std::function
作为默认参数的模板化函数时,我只能创建该函数的一个模板实例,否则会出现错误。
考虑以下代码:
#include <functional>
template<bool B>
void wut(std::function<void()> f = []() {})
{
f();
}
int main() {
wut<false>(); // works
wut<false>(); // still works
wut<true>(); // error
return 0;
}
编译此代码时出现以下错误:
{standard input}: Assembler messages:
{standard input}:28: Error: symbol `_ZNSt14_Function_base13_Base_managerIUlvE_E10_M_managerERSt9_Any_dataRKS3_St18_Manager_operation' is already defined
{standard input}:127: Error: symbol `_ZNSt17_Function_handlerIFbvEUlvE_E9_M_invokeERKSt9_Any_data' is already defined
这是一个 gcc 错误(在 7.3 版后看起来已修复)我们可以通过查看部分 [expr.prim.lambda.capture]p9:
来了解这一点A lambda-expression appearing in a default argument shall not implicitly or explicitly capture any entity. [Example:
void f2() { int i = 1; void g1(int = ([i]{ return i; })()); // ill-formed void g2(int = ([i]{ return 0; })()); // ill-formed void g3(int = ([=]{ return i; })()); // ill-formed void g4(int = ([=]{ return 0; })()); // OK void g5(int = ([]{ return sizeof i; })()); // OK }
—end example]
作为 IDEOne 的替代品,您可以使用与 gcc 和 clang 版本保持同步的 Wandbox,请参阅 your example live there。
看起来像是一个编译器错误。
然而,在头文件中使用 lambda 充满了 ODR 问题。所以我会避免它。
在c++17中:
template<auto X>
struct always_return {
template<class...Args>
auto operator()(Args&&...)const{ return X; }
};
template<bool B>
void wut(std::function<bool()> f = always_return<false>{})
{
或在c++11:
template<class T>
struct always_return_t {
T t;
template<class...Args>
auto operator()(Args&&...)const{ return t; }
};
template<class T>
always_return_t<typename std::decay<T>::type> always_return(T&&t) {
return {std::forward<T>(t)};
}
template<bool B>
void wut(std::function<bool()> f = always_return(false)){