2012-03-23 4 views
1

Я пытался использовать локальный класс для моделирования локальных функций. Локальный класс определяет несколько статических вспомогательных функций, где каждой статической функции необходимо получить доступ к статическому массиву, определенному в области функций. Дело работает для нормальной функции, но при использовании функции шаблона у меня возникает ошибка связи. Код:Локальные шаблоны классов и функций

#include <iostream> 

double test_local (double x) 
{ 
    static const double coeff[3]={ 0, 1, 2 }; 

    struct local_functions 
    { 
     static double f0 (double x) 
     { 
      static const double c0=coeff[0]+coeff[1]; 
      return c0+x; 
     } 

     static double f1 (double x) 
     { 
      static const double c1=coeff[1]+coeff[2]; 
      return c1+x; 
     } 

     static double f2 (double x) 
     { 
      static const double c2=coeff[2]+coeff[0]; 
      return c2+x; 
     }  
    }; 

    return local_functions::f0(x)+local_functions::f1(x)+local_functions::f2(x); 
} 

template<class t> 
t test_local_tmpl (t x) 
{ 
    static const t coeff[3]={ 0, 1, 2 }; 

    struct local_functions 
    { 
     static t f0 (double x) 
     { 
      static const t c0=coeff[0]+coeff[1]; 
      return c0+x; 
     } 

     static t f1 (t x) 
     { 
      static const t c1=coeff[1]+coeff[2]; 
      return c1+x; 
     } 

     static t f2 (t x) 
     { 
      static const t c2=coeff[2]+coeff[0]; 
      return c2+x; 
     } 
    }; 

    return local_functions::f0(x)+local_functions::f1(x)+local_functions::f2(x); 
} 

int main (int argc, char** argv) 
{ 
    double result=test_local (1e0); 

    // uncommenting next line generates a linking error 
    // double result_tmpl=test_local_tmpl (1e0); 

    std::cout << result << std::endl; 
    return 0; 
} 

функция не шаблон отлично работает (он печатает 9), в то время как при попытке вызвать версию шаблона, он отлично компилируется, но не связывает под г ++ - 4.6:

g++ -c -g local_class.cpp && g++ local_class.o -o local_class 
Undefined symbols: 
    "coeff", referenced from: 
     double test_local_tmpl<double>(double)::local_functions::f2(double) in local_class.o 
     double test_local_tmpl<double>(double)::local_functions::f2(double) in local_class.o 
     double test_local_tmpl<double>(double)::local_functions::f1(double) in local_class.o 
     double test_local_tmpl<double>(double)::local_functions::f1(double) in local_class.o 
     double test_local_tmpl<double>(double)::local_functions::f0(double) in local_class.o 
     double test_local_tmpl<double>(double)::local_functions::f0(double) in local_class.o 
ld: symbol(s) not found 
collect2: ld returned 1 exit status 

Является ли это ожидаемым beahaviour, я что-то пропустил или что?

+0

Возможный дубликат [Использование локальных классов с алгоритмами STL] (http://stackoverflow.com/questions/742607/using-local-classes-with-stl-algorithms). Ограничение не использования локальных классов в шаблонах было удалено из C++ 11, не знаю, реализует ли gcc4.6 это, хотя, по другой мысли, я даже не уверен, что это дубликат, мне трудно обработайте вопрос с помощью такого кода. –

+4

Плохое форматирование. – Nawaz

+0

@ DavidRodríguez-dribeas: У меня проблемы при связывании **, код компилируется нормально **. В любом случае добавление флага -std = C++ 0x дает ту же проблему. – Giuliano

ответ

1

Это ошибка GCC. В коде отсутствует ошибка. Пожалуйста, напишите отчет об ошибке.

+0

Я так думаю ..... – Nawaz

+0

Кстати, он исправлен в gcc-4.5.1. – Nawaz

+0

@ Наваз хороший, я добавлю это к своему ответу. –

0

Обходной путь, чтобы обойти проблему, ожидая подлинного решения от разработчиков gcc. Я должен признать, что моим окончательным решением было перейти на традиционную реализацию без вспомогательных функций. Он гораздо менее изящный (конечно), но работает, и все это имеет значение.

В любом случае я представляю здесь «решение», поскольку он может быть полезен в других контекстах (возможно). Надеюсь, что форматирование кода не повредит вашим глазам :) на этот раз.

#include <iostream> 
#include <complex> 

template<class t> 
t test_local_tmpl (t x) 
{ 
    struct local_functions 
    { 
    static const t* coeff() 
    { 
     static const t c[]={0,1,2}; 
     return c; 
    } 

    static t f0 (t x) 
    { 
     static const t c0=coeff()[0]+coeff()[1]; 
     return c0+x; 
    } 

    static t f1 (t x) 
    { 
     static const t c1=coeff()[1]+coeff()[2]; 
     return c1+x; 
    } 

    static t f2 (t x) 
    { 
     static const t c2=coeff()[2]+coeff()[0]; 
     return c2+x; 
    } 
    }; 

    return local_functions::f0(x)+local_functions::f1(x)+local_functions::f2(x); 
} 

int main (int argc, char** argv) 
{ 
    std::cout << test_local_tmpl (1e0) << std::endl; 
    std::cout << test_local_tmpl (std::complex<double>(1e0)) << std::endl; 
    return 0; 
} 

И выход

$ g++-mp-4.6 -c -g local_class.cpp && g++-mp-4.6 local_class.o -o local_class 
$ ./local_class 
9 
(9,0) 

Во всяком случае, кажется, что местные классы такой угол особенность в языке, что, вероятно, они никогда не сделали поездку из из книги Alexandrescu на конструкции C++. Тот факт, что ошибка не была обнаружена, подтверждает это ИМХО.

Смежные вопросы