On 10.07.2020 05:34, Daniel P wrote:
> #include <string>
> #include <utility>
> #include <type_traits>
> #include <cstdint>
>
> template <class T, class Enable = void>
> class A
> {
> };
I don't see the `Enable` parameter being used for anything?
> template<class CharT,class Traits,class Allocator>
> class A<std::basic_string<CharT,Traits,Allocator>>
> {
> public:
> template <class ChT = CharT>
> typename std::enable_if<sizeof(ChT) == sizeof(uint8_t)>::type
> f() const
Tip 1: using `sizeof(uint8_t)` does two things: checking that `uint8_t`
exists, and producing the compile time value 1.
I would separate those aspects.
In this code `uint8_t` is not formally guaranteed to exist even on an
8-bit byte machine, because there is no `using std::uint8_t`. However,
that's not the problem. Adding that declaration doesn't fix things.
Tip 2: instead of mind-boggling gymnastics to embed to `enable_if` in
the return type specification, just use a defaulted type parameter. It's
allowed on functions since C++11.
> {
> }
>
> template <class ChT = CharT>
> typename std::enable_if<sizeof(ChT) != sizeof(uint8_t)>::type
> f() const
> {
> A<std::string> convert;
> convert.f(); // (*)
> }
> };
>
> int main()
> {
> A<std::string> a;
>
> a.f(); // (**)
> }
>
> With vs2019, Version 16.6.0, C++17, I get
Huh, version 16.6.0?
Oh, the Visual Studio version. OK. The compiler with that version of VS
is version 14.26, with `_MSC_VER` = 1926, and with the command line
compiler reporting version number 19.26.28806.
The offset is due to the higher version number going all the way back to
Lattice C, the compiler that Microsoft built on for their first Visual C
(hence, compiler name "cl.exe", or so I believe), while the lower
version number only goes back to the introduction of Visual C++.
> Error C2039 'f': is not a member of 'A<std::basic_string<char,std::char_traits<char>,std::allocator<char>>,void>'
>
> at (*) and (**).
>
> It compiles with earlier versions of vs.
It should compile. Wait a little, I'll check.
------------------------------------------------------------------------------------
[P:\temp]
> g++64 --version | find "++"
g++ (GCC) 9.2.0
[P:\temp]
> g++64 foo.cpp
[P:\temp]
> cl /nologo- 2>&1 | find "++"
Microsoft (R) C/C++ Optimizing Compiler Version 19.26.28806 for x64
[P:\temp]
> echo %CL%
/nologo /utf-8 /EHsc /GR /permissive- /FI"iso646.h" /std:c++17
/Zc:__cplusplus /W4 /wd4459 /D _CRT_SECURE_NO_WARNINGS /D
_STL_SECURE_NO_WARNINGS
[P:\temp]
> cl foo.cpp /Feb
foo.cpp
foo.cpp(26): error C2039: 'f': is not a member of
'A<std::basic_string<char,std::char_traits<char>,std::allocator<char>>,void>'
foo.cpp(25): note: see declaration of
'A<std::basic_string<char,std::char_traits<char>,std::allocator<char>>,void>'
foo.cpp(26): note: This diagnostic occurred in the compiler generated
function 'std::enable_if<sizeof(ChT)!=1,void>::type
A<std::basic_string<_Elem,_Traits,_Alloc>,void>::f(void) const'
foo.cpp(28): note: see reference to class template instantiation
'A<std::basic_string<_Elem,_Traits,_Alloc>,void>' being compiled
foo.cpp(34): error C2039: 'f': is not a member of
'A<std::basic_string<char,std::char_traits<char>,std::allocator<char>>,void>'
foo.cpp(25): note: see declaration of
'A<std::basic_string<char,std::char_traits<char>,std::allocator<char>>,void>'
------------------------------------------------------------------------------------
Hm!
I'm not sure what you're trying to do, but I would try something else,
with less templating.
- Alf