явное создание экземпляра функции с использованием decltype: работа на g++, но не на Visual C++

Эти коды работают на G++, но не для Visual C++.

#include <iostream>
template<typename T> void foo( T& t,int some_parameter){}
template decltype(foo<int>) foo;
int main(){
    std::cout << "Hello, world!\n";
}

Вот ошибка из Visual C++: -

ошибка C2206: 'foo': typedef нельзя использовать для определения функции

Поощрение: я не хочу повторять сигнатуру функции для явного создания экземпляра.
Я изменил код из https://stackoverflow.com/a/28356212 .

Какой из них неправильный? Как обойти это в Visual C++?

Текущий непрямой обходной путь

Днем позже я нашел лучший обходной путь: https://stackoverflow.com/a/50350144.

#include <tuple>
template<typename... Ts>auto instantiate() {
    static auto funcs = std::tuple_cat(std::make_tuple(
        foo1<Ts>,
        foo2<Ts>
    )...);
    return &funcs;
}
template auto instantiate<int, double>();

Однако в Visual C++ это работает только при компиляции foo.cpp с включенной оптимизацией: -

  • Custom или Disabled(/Od) не подходит.
  • Используйте все /O1, /O2 и /Ox в порядке.
  • Without any of /Od, /O1, /O2 and /Ox :-
    • Just /Og is OK.
    • Просто /Oi, /Ot, /Oy, /Ob2, /GF и /Gy не подходят.
    • Использовать все флаги в двух строках выше можно.

Временное решение (работа с /Od): вызов std::tuple_size<decltype(instantiate<int, double>())> внутри фиктивной функции в .cpp. Затем объявите фиктивную функцию в заголовке.


person cppBeginner    schedule 21.09.2020    source источник
comment
это не может работать таким образом - что должно произойти, если у вас более одного foo?   -  person Bernd    schedule 21.09.2020
comment
@Bernd Ошибка компиляции? Скажем, меня волнует только ситуация, что во вселенной есть только один foo.   -  person cppBeginner    schedule 21.09.2020
comment
Более удобная ссылка: godbolt.org/z/1nx3cf   -  person Marek R    schedule 21.09.2020
comment
почему template стоит перед decltype(foo<int>) foo;?   -  person Marek R    schedule 21.09.2020
comment
@Marek R :: Спасибо за лучшую ссылку. Извините, я не знаю причины, поэтому не могу ответить на ваш.   -  person cppBeginner    schedule 21.09.2020
comment
@ B0FEE664 :: Спасибо, теперь это компилируется в VC. Я проверю, действительно ли он создает экземпляр функции.   -  person cppBeginner    schedule 21.09.2020


Ответы (1)


Я считаю, что msvc неверен. Короче говоря, явное создание экземпляра — это просто template, за которым следует обычное объявление.

Если вы следуете грамматике [temp.explicit]

explicit-instantiation:
    template declaration
declaration:
    block-declaration
block-declaration:
    simple-declaration
simple-declaration:
    decl-specifier-seq init-declarator-list;
decl-specifier-seq:
    decl-specifier
decl-specifier:
    defining-type-specifier
defining-type-specifier:
    simple-type-specifier
simple-type-specifier:
    decltype-specifier
decltype-specifier:
    decltype ( expression )

Я не верю, что для этого есть работа. По-видимому, msvc рассматривает decltype как псевдоним типа и отклоняет любые предполагаемые определения с сигнатурами, которые являются псевдонимами. Эти тоже отвергнуты

using F = decltype(foo<int>);
template F foo;
extern template F foo;  // not even a definition

Тем не менее, он принимает эти

F bar;
decltype(foo<int>) baz;
person Passer By    schedule 21.09.2020