繁体   English   中英

带有默认std :: function参数的模板化函数会导致符号[...]已定义

[英]Templated function with defaulted std::function parameter causes symbol […] already defined

我只是碰到了一些奇怪的东西。 我想知道这是不是一个错误,如果不是,我希望有人可以解释这个问题。

我的问题是,当我创建一个模板化函数,它将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;
}

https://ideone.com/VlVcUv

编译此代码时,我收到以下错误:

{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 bug(看起来在7.3之后修复)我们可以通过查看[expr.prim.lambda.capture] p9节来看到这个:

出现在默认参数中的lambda表达式不得隐式或显式捕获任何实体。 [例:

 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 } 

- 末端的例子]

作为IDEOne的替代方案,您可以使用Wandbox与gcc和clang版本保持同步,请查看您的示例

看起来像编译器错误。

但是在头文件中使用lambdas充满了ODR问题。 所以我会避免它。

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>{})
{

或者在

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)){

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM