Локальные шаблоны классов и функций - PullRequest
1 голос
/ 23 марта 2012

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

#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), в то время как, если я пытаюсь вызвать версию шаблона, она прекрасно компилируется, но не связывается при g ++ - 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

Это ожидаемое поведение, я что-то упустил или что?

Ответы [ 2 ]

1 голос
/ 23 марта 2012

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

0 голосов
/ 24 марта 2012

Обходной путь для обхода проблемы в ожидании подлинного решения от разработчиков 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)

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...