функция друга в CUDA C ++ - PullRequest
0 голосов
/ 27 мая 2018

Я работаю над проблемой, заключающейся в том, что класс A и B объявлены в пространстве имен test0, а функция-друг f класса A объявлена ​​в пространстве имен test1.Функция f получает ссылку на объект класса B в качестве параметра.Вот упрощенный пример.

namespace test0 {
    class B;
}

namespace test1 {
    void f(test0::B& b);
}

namespace test0 {
    class A {
        friend void test1::f(test0::B& b);
    };
}

Код работает с g ++.Но nvcc выдает следующую ошибку компиляции:

a.cu:11:22: error: ‘B’ has not been declared
        friend void test1::f(test0::B& b);
                    ^
a.cu:11:27: error: ‘void test1::f(int&)’ should have been declared inside ‘test1’
        friend void test1::f(test0::B& b);
                        ^

Не могли бы вы помочь мне разобраться в чем проблема?Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 30 мая 2018

После проверки командой разработчиков NVIDIA выясняется, что это может быть причиной ошибки в компиляторе gnu.Это правда, что внешняя обработка цепочкой инструментов nvcc создает код хоста (переданный компилятору хоста), который отбрасывает квалификацию пространства имен для типа b, но это должно быть приемлемо, поскольку B ужебыло объявлено в test0 пространстве имен.

Похоже, что уже было сообщено сообществу gnu.

В качестве вспомогательной точки данных, clang ++ 3.9.1 onFedora 25 компилирует код, указанный в ответе , заданном @talonmies, без ошибок и предупреждений.При тестировании через gnu 6.4.1 на Fedora25 цепочка инструментов gnu по-прежнему выдает ошибку.Я не претендую на это как на доказательство, просто на предположение, что утверждение об ошибке в gnu может быть правильным.Я не эксперт по языку.Кроме того, я не хочу здесь спорить об этом;Это не цель этого вопроса или ответа.

Команда разработчиков NVIDIA взяла рассматриваемый вопрос и надеется найти исправление или обходной путь в будущем выпуске CUDA.

Тем временем,Предлагаемый обходной путь на уровне источника - использовать фиктивную typedef для B в классе A.т.е.:

class A {
    typedef B dummy_t;
    friend void test1::f(dummy_t & b);
};

ОБНОВЛЕНИЕ:

Проблема должна быть решена в CUDA 10.1.105 (CUDA 10.1)

0 голосов
/ 27 мая 2018

Важно понимать, что nvcc не является компилятором, это драйвер компилятора , и в обоих случаях код компилируется с помощью gcc, а ошибка является ошибкой, сгенерированной gcc.Если вы поместите этот код в файл расширения .cc и скомпилируете его с помощью nvcc, ошибки не будет.

Но при компиляции кода CUDA (в данном случае в файле .cu) естьнекоторые промежуточные этапы обработки между вашим кодом и финальным этапом g ++, который его компилирует.В сущности происходит то, что ваш код преобразовывается интерфейсным синтаксическим анализатором CUDA C ++ в следующий код:

# 1
# 2
namespace test0 { 
# 3
    class B; 
# 4
}
# 6
namespace test1 { 
# 7
    void f(test0::B & b); 
# 8
}
# 10
namespace test0 { 
# 11
    class A { 
# 12
        friend void test1::f(B & b); 
# 13
    }; 
# 14
}

сравните это с исходным friend void test1::f(test0::B& b);, и вы увидите, что пространство имен былораздетый проходом cudafe ++.Я не знаю, почему он был удален, но это является источником ошибки.

Я бы порекомендовал сообщать об этом как об ошибке в NVIDIA, если это реальная проблема вваше заявление.

...