I try to make a class method that should execute the part of code only if the static condition is true. Otherwise it shouldn’t be executed or even compiled. Below is a simplified variant of the code I try to make:
#include <cstdio>
#include <cstdint>
#include <type_traits>
class inet_socket {
uint32_t ip;
};
class unix_file_socket {
char path[64];
};
template <typename protocol>
class server
{
public:
protocol socket;
void do_something();
};
template <typename protocol>
void server<protocol>::do_something()
{
/* ... */
if (std::is_same<protocol, unix_file_socket>::value)
// use static check if protocol is unix file
// and if it is then delete file
std::remove(socket.path);
}
int main()
{
server<inet_socket> srv;
srv.do_something();
}
I thought if protocol
is not unix_file_socket
then the compiler excludes if (false)
statement and string std::remove(socket.path)
won’t be included, so there won’t be error of getting field path
that is non-existent in non unix_file_socket
protocols. But actually I get an error:
file.cpp: In instantiation of ‘void server<protocol>::do_something() [with protocol = inet_socket]’:
file.cpp:33:22: required from here
file.cpp:27:28: error: ‘class inet_socket’ has no member named ‘path’
27 | std::remove(socket.path);
| ~~~~~~~^~~~
Then I tried to make a template method that will have two partial specializations. One will delete file, other won’t. Then I’d call only the method that is suitable for the protocol, so it should be the only method that will be compiled for the protocol and the error should not appear. Changes:
template <typename protocol>
class server
{
public:
protocol socket;
void do_something();
template <bool> void remove_socket();
};
template <typename protocol>
void server<protocol>::do_something()
{
/* ... */
remove_socket<std::is_same<protocol, unix_file_socket>::value>();
// static check if protocol is unix file
// and if it is then use method that deletes file
// else use method that doesn't
}
template <typename protocol>
template <>
void server<protocol>::remove_socket<true>()
{
// if socket is unix file
std::remove(socket.path);
}
template <typename protocol>
template <>
void server<protocol>::remove_socket<false>()
{ /* if it is inet socket do nothing */ }
I had a hope it works, but I got syntax error:
file.cpp:34:11: error: invalid explicit specialization before ‘>’ token
34 | template <>
| ^
file.cpp:34:11: error: enclosing class templates are not explicitly specialized
file.cpp:42:11: error: invalid explicit specialization before ‘>’ token
42 | template <>
| ^
file.cpp:42:11: error: enclosing class templates are not explicitly specialized
I tried to erase lines template <>
, but that didn’t work anyway. How to make it work?
1