Шаблонная функция с параметром по умолчанию std :: function приводит к тому, что символ [...] уже определен - PullRequest
0 голосов
/ 24 октября 2018

Я просто столкнулся с чем-то странным.Интересно, если это ошибка, и если нет, я надеюсь, что кто-то может объяснить проблему.

Моя проблема в том, что когда я создаю шаблонную функцию, которая принимает 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

Ответы [ 2 ]

0 голосов
/ 24 октября 2018

Похоже на ошибку компилятора.

Однако использование лямбд в заголовочных файлах чревато проблемами 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)){
0 голосов
/ 24 октября 2018

Это ошибка gcc (которая выглядит исправленной после версии 7.3), мы можем увидеть это, просмотрев раздел [expr.prim.lambda.capture] p9 :

Лямбда-выражение, появляющееся в аргументе по умолчанию, не должно явно или явно захватывать какую-либо сущность.[Пример:

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, см. твой пример там живет .

...