Это, похоже, другое: «Кто делает это хорошо?» вопрос, так как gcc 6.0.0 и clang 3.7.0 ведут себя иначе.Перенаправление аргумента, отличного от типа, вызывает различное поведение в шаблоне переменной
Давайте предположим, что мы имеем переменную шаблон, который принимает const char *
как не аргумент шаблона и специализирован для данного указателя:
constexpr char INSTANCE_NAME[]{"FOO"};
struct Struct{ void function() const { std::cout << __PRETTY_FUNCTION__; } };
std::ostream &operator <<(std::ostream &o, const Struct &) { return o << INSTANCE_NAME; }
template <const char *> char Value[]{"UNKNOWN"};
// spezialization when the pointer is INSTANCE_NAME
template < > Struct Value<INSTANCE_NAME>{};
Обратите внимание, что переменная шаблона имеют различные типы в зависимости от специализации. Десять у нас есть две функции шаблона, каждый из одного принимает const char *
как, не аргумент шаблона и вперед его переменного шаблон:
template <const char *NAME> void print()
{
std::cout << Value<NAME> << '\n';
}
template <const char *NAME> void call_function()
{
Value<NAME>.function();
}
Тогда вызов этого функция результаты в разных режимах:
int main()
{
print<INSTANCE_NAME>();
call_function<INSTANCE_NAME>();
return 0;
}
лязг 3.7.0 печатает FOO
и void Struct::function() const
(Как я ожидал) в то время как GCC 6.0.0 не может скомпилировать с ошибкой ниже:
запрос члена «функции» в «Value», который имеет тип неклассовую «полукокса [8]»
Я почти уверен, что НКУ не удались вперед в шаблоне, не аргумент типа NAME
переменного шаблона Value
в функции call_function
и по этой причине он выбирает неразделенный переменный шаблон, который является один с 'char [8]'
типом ...
Он действует так, как будто он копирует аргумент шаблона. Это происходит только при вызове функции-члена объекта, если мы прокомментируем тело call_function
, выход FOO
не UNKNOWN
, поэтому в функции print
пересылка работает даже в gcc.
Так
- Что правильное поведение? (mi bet for clang)
- Как я могу открыть биг-код для компилятора, который делает это неправильно?
@ BЈовић вы можете, если 'const char *' имеют внешнюю связь ([см. Этот ответ] (http://stackoverflow.com/a/16402606/499359)). При внешней связи он всегда будет иметь тот же адрес; думайте об этом, как будто это «int». –
Просто примечание: наличие совершенно разных конструкций под названием 'FOO',' Foo' и 'foo' затрудняет мысленный анализ вашего примера. 'MyCharP',' MyStruct' и 'myFun' или подобное было бы проще. – TartanLlama
@TartanLlama Я изменил имена, спасибо за предложение :) –