Войти
ПрограммированиеФорумОбщее

template<const char *>

#0
17:59, 24 ноя. 2017

Ради прикола тут крутил один старый сырец и нашел темплейт со строкой в качестве аргумента(бред конечно ну да ладно) - и увидел что это не компилится ни 17ой ни 15ой студией.

Накидал хелловорлд

#include <iostream>
using namespace std;

template <const char * s>
void g()
{
    cout << s << endl;
}

const char sss[] = "test";

int main() {
    g<sss>();
}

error C2970: 'g': template parameter 's': 'sss': an expression involving objects with internal linkage cannot be used as a non-type argument

Я точно помню несколько лет назад на 2008й студии это компилилось(но это не точно). Зашел на саппорт мс - там куча замечаний по нон тайп аргументам - по ходу в студийном компиле что-то сломали с этими вашими новыми стандартами.

ЗЫ
на clang и gcc всё работает.

ЗЫ2
У кого осталась 2008я - скомпильте, если не прокатит можно попробовать static const char sss[] = "test";


#1
18:28, 24 ноя. 2017

Откопали 2008ю тоже не компилится хмм - я точно помню, что это собиралось причем на студии

#2
18:35, 24 ноя. 2017

fsmoke
> an expression involving objects with internal linkage cannot be used as a
> non-type argumen

Попробуй агрумент сделать глобальным нестатическим указателем на строку.

#3
18:44, 24 ноя. 2017

Panzerschrek[CN]

error C2672: 'g': no matching overloaded function found
error C2975: 's': invalid template argument for 'g', expected compile-time constant expression
note: see declaration of 's'

#4
19:27, 24 ноя. 2017

Будь в будущем, фигарь стандарт C++17 template<auto s>.

#5
19:34, 24 ноя. 2017
const char sss[] = "test";
Убери к чертям const.
#6
22:08, 24 ноя. 2017

constexpr char sss[] = "test"; собирается.

#7
5:12, 25 ноя. 2017

fsmoke
Если коротко - адреса одного и того-же строкового литерала и литералов "совпадающих по содержимому" могут быть разными даже в пределах одного translation unit (implementation defined).
Т.е. c

map<const char*, int> m; m["moohaha"] = 42;
можно влететь.
#8
15:55, 25 ноя. 2017

GermanAizek
> Убери к чертям const.

и в правду, собираецо!! - мистика

Dimich
> constexpr char sss[] = "test"; собирается.
опровергаю - у меня не собирается - пишет тоже самое

#9
15:59, 25 ноя. 2017

вот что ответили из МС:

Hi.
Using address of objects whose name has internal linkage wasn't allowed at C++14, but C++17(approved at Nov. 11) now allows. And VS 15.4 have not implement this change yet.
But it may be available in VS 15.5 which may come soon.

так что ждем..

#10
16:04, 25 ноя. 2017
loyso
> Если коротко
+ Показать
#11
23:53, 25 ноя. 2017
fsmoke
> и в правду, собираецо!! - мистика
fsmoke
> опровергаю - у меня не собирается - пишет тоже самое
fsmoke
> Using address of objects whose name has internal linkage wasn't allowed at
> C++14, but C++17

Я надеюсь, все понимают и вполне отдают себе отчёт в том, что это же долбаный стыд? Понятно, что сделать мы ничего не можем, но нужно хотя бы понимать, что это долбаный стыд. В эпоху, когда мир рушится, шизофрения в стандартах прогрессирует, а посреди всего - потерянный, охваченный ужасом слабый человеческий моск, его последний путеводный проблеск в море мрака и безобразия - память о том, что такое "хорошо" и что такое "плохо".

#12
10:01, 29 ноя. 2017

fsmoke
> + Показать

Исключительно референса ради:

const char prefix[] = "prefix";
const char prefix_suffix[] = "prefixsuffix";
const char suffix[] = "suffix";

// что у нас за компилятор?
// static_assert(suffix == prefix_suffix + sizeof(prefix));

int main() {
    const char suffix2[] = "suffix";
    // что у нас за компилятор?
   // static_assert(suffix2 != suffix);

    //  возьмем g из примера сверху.
    g<suffix>();
    g<suffix2>();
    g<"suffix">(); //  уже третий адрес, третий инстанс?
    // непонятно - какие инстансы g компилятору инстанциировать. 
    // И совпадает ли template instance interning со string interning.
}

#13
17:12, 29 ноя. 2017

fsmoke
> Hi.
> Using address of objects whose name has internal linkage wasn't allowed at
> C++14, but C++17(approved at Nov. 11) now allows. And VS 15.4 have not
> implement this change yet.
> But it may be available in VS 15.5 which may come soon.
error C2970: 'g': template parameter 's': 'sss': an expression involving objects with internal linkage cannot be used as a non-type argument
сделай
extern const char sss[] = "test";

Тут надо знать 2 хитрых факта из мира С++, чтобы не возникло вопроса, почему так.
1)

By default, in C++ all const objects declared at global namespace scope have internal linkage. That is, they are, in effect, static const. If you define a const object and give it the extern qualifier you give it external linkage.

2) Темплейты должны везде одинаково разворачиваться, поэтому используется конечный глобальный адрес. На этапе линковки адреса объектов с внутренней ликновкой могут меняться (а, значит, программа может поломаться, ведь от этого адреса зависит то, какая специализация темплейта должна была использоваться). Чтобы избежать такой неприятной ситуации они и запретили использовать такие обьекты в качестве аргумента. (Дисклеймер: это все моя версия, почему так)

ПрограммированиеФорумОбщее

Тема в архиве.