llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
29.09k stars 11.99k forks source link

extern template - clang produce error/msvc ok #56066

Open marakew opened 2 years ago

marakew commented 2 years ago
#include <string>
#include <vector>

extern template std::vector<std::string>;

int main(){return 0;}
> clang-cl.exe /std:c++20 nothing.cpp
nothing.cpp(5,17): error: declaration does not declare anything
extern template std::vector<std::string>;
                ^~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
llvmbot commented 2 years ago

@llvm/issue-subscribers-clang-frontend

hvdijk commented 2 years ago

The standard syntax for this is extern template class std::vector<std::string>; or extern template struct std::vector<std::string>;. This works with all compilers. MSVC also allows the class/struct keyword to be omitted (even under /Za), but clang has not included this in its -fms-extensions mode.

marakew commented 2 years ago

can you please show where this standard syntax at standard ?

i see

https://en.cppreference.com/w/cpp/language/class_template

export template < parameter-list > class-declaration

class-declaration - a class declaration. The class name declared becomes a template name.

there are no kerwords about struct or class

2022-06-17 6:04 GMT+03:00, Harald van Dijk @.***>:

The standard syntax for this is extern template class std::vector<std::string>; or extern template struct std::vector<std::string>;. This works with all compilers. MSVC also allows the class/struct keyword to be omitted (even under /Za), but clang has not included this in its -fms-extensions mode.

-- Reply to this email directly or view it on GitHub: https://github.com/llvm/llvm-project/issues/56066#issuecomment-1158439900 You are receiving this because you authored the thread.

Message ID: @.***>

hvdijk commented 2 years ago

there are no kerwords about struct or class

If you click through on your link to class-declaration, it shows that a class-declaration needs to start with class-key, i.e. class, struct, or union. (Edit: but that's not the relevant bit, the relevant bit is if you scroll down on your link, under "Explicit instantiation", where it also says class-key.)

marakew commented 2 years ago

how to compile with clang this example ?

#include <string>

template<typename A, int B>
struct BASE
{
};

using BASE_INST = BASE<std::string,2>;
extern template BASE_INST;

int main(){return 0;}

with or without struct key clang cant compile with msvc all ok

nothing.cpp(10,17): error: declaration does not declare anything
extern template BASE_INST;
                ^~~~~~~~~
1 error generated.
nothing.cpp(10,24): error: type alias 'BASE_INST' cannot be referenced with a struct specifier
extern template struct BASE_INST;
                       ^
nothing.cpp(9,7): note: declared here
using BASE_INST = BASE<std::string,2>;
      ^
1 error generated.
hvdijk commented 2 years ago

how to compile with clang this example ?

I believe there is currently no standard way of performing explicit template instantiations that avoid the class name. This is similar to how in earlier versions of C++, there was no way of declaring friends using typedef names: friend class T; required T to be the class name, and friend T; was an error. It took an update to the C++ standard to add support for the latter, and then for compilers to implement the update to the rules. For explicit template instantiations, a similar process would need to happen for this to become accepted in all compilers.

For clang specifically, as it has a mode where it supports Microsoft extensions, it could potentially be added to that mode if there is enough code out there that compiles successfully with MSVC but fails to compile with clang because of this.