模板完成后停止编译 used/resolved
Stop compilation when a template has been used/resolved
这个 MCVE:
#include <stdio.h>
#include <time.h>
#define MAX_LENGTH_DATETIME 25
template <typename T>
char * convertUnixTimeToChar( time_t unixTime, T )
{
(void) unixTime;
#pragma message "2nd parameter in convertUnixTimeToChar() must be of type <char [MAX_LENGTH_DATETIME]>."
exit(1);
};
template<size_t N>
char * convertUnixTimeToChar( time_t unixTime, char (&destination) [N] )
{
if ( N < MAX_LENGTH_DATETIME )
{
printf( "Overflow in convertUnixTimeToChar(): destination size [%ld] must be at least [%u]", N, MAX_LENGTH_DATETIME );
exit(1);
}
struct tm * tmNow;
tmNow = localtime( &unixTime );
strftime( destination, MAX_LENGTH_DATETIME - 1, "%Y-%m-%d %H:%M:%S", tmNow );
return destination;
};
int main()
{
char buffer [MAX_LENGTH_DATETIME ];
printf( "Converted unix time=%s\n", convertUnixTimeToChar( 1487585045, buffer ) );
}
我的问题:
我想在编译时显示#pragma message "2nd parameter in convertUnixTimeToChar() must be of type <char [MAX_LENGTH_DATETIME]>."
来自 gcc 的消息仅当 类型为char *
已传递给 convertUnixTimeToChar()
因为第一个模板已解析。现在我总是收到这条消息。
换句话说,如果传递了错误的参数,编译应该会失败,而不是当程序是 运行 [在这种情况下,我必须使用 printf
而不是 #pragma
得到通知]。
传递类似 char [25]
的内容可解析第二个模板,一切正常!
如果模板已被物理地用于代码生成,有没有一种方法可以有条件地停止编译并显示错误消息?
使用这些开关使用 gcc 4.9.4 编译:-Wall -Werror -Wextra -std=c++11 -O3
再一次,最优解是"don't do anything at all"。
完全删除 catch-all 重载将使编译器为任何无法匹配 char (&destination) [N]
.
的参数产生错误
如果你想要花哨并添加自己的错误消息,你可以在 catch-all:
中使用依赖 static_assert
template <class..., class T>
constexpr T &&depend(T &&o) {
return std::forward<T>(o);
}
template <typename T>
char *convertUnixTimeToChar( time_t, T&& )
{
static_assert(depend<T>(false), "2nd parameter in convertUnixTimeToChar() must ...");
}
并不是说这可能不是 更好的 解决方案,因为您抓住了 convertUnixTimeToChar
的整个重载集并将其陷入硬错误,该死的 SFINAE。如果有人想为他们自己的类型添加重载,他们将必须确保他们的重载比这个爆炸性的更好catch-all,这是痛苦多于收获。
这个 MCVE:
#include <stdio.h>
#include <time.h>
#define MAX_LENGTH_DATETIME 25
template <typename T>
char * convertUnixTimeToChar( time_t unixTime, T )
{
(void) unixTime;
#pragma message "2nd parameter in convertUnixTimeToChar() must be of type <char [MAX_LENGTH_DATETIME]>."
exit(1);
};
template<size_t N>
char * convertUnixTimeToChar( time_t unixTime, char (&destination) [N] )
{
if ( N < MAX_LENGTH_DATETIME )
{
printf( "Overflow in convertUnixTimeToChar(): destination size [%ld] must be at least [%u]", N, MAX_LENGTH_DATETIME );
exit(1);
}
struct tm * tmNow;
tmNow = localtime( &unixTime );
strftime( destination, MAX_LENGTH_DATETIME - 1, "%Y-%m-%d %H:%M:%S", tmNow );
return destination;
};
int main()
{
char buffer [MAX_LENGTH_DATETIME ];
printf( "Converted unix time=%s\n", convertUnixTimeToChar( 1487585045, buffer ) );
}
我的问题:
我想在编译时显示#pragma message "2nd parameter in convertUnixTimeToChar() must be of type <char [MAX_LENGTH_DATETIME]>."
来自 gcc 的消息仅当 类型为char *
已传递给 convertUnixTimeToChar()
因为第一个模板已解析。现在我总是收到这条消息。
换句话说,如果传递了错误的参数,编译应该会失败,而不是当程序是 运行 [在这种情况下,我必须使用 printf
而不是 #pragma
得到通知]。
传递类似 char [25]
的内容可解析第二个模板,一切正常!
如果模板已被物理地用于代码生成,有没有一种方法可以有条件地停止编译并显示错误消息?
使用这些开关使用 gcc 4.9.4 编译:-Wall -Werror -Wextra -std=c++11 -O3
再一次,最优解是"don't do anything at all"。
完全删除 catch-all 重载将使编译器为任何无法匹配 char (&destination) [N]
.
如果你想要花哨并添加自己的错误消息,你可以在 catch-all:
中使用依赖static_assert
template <class..., class T>
constexpr T &&depend(T &&o) {
return std::forward<T>(o);
}
template <typename T>
char *convertUnixTimeToChar( time_t, T&& )
{
static_assert(depend<T>(false), "2nd parameter in convertUnixTimeToChar() must ...");
}
并不是说这可能不是 更好的 解决方案,因为您抓住了 convertUnixTimeToChar
的整个重载集并将其陷入硬错误,该死的 SFINAE。如果有人想为他们自己的类型添加重载,他们将必须确保他们的重载比这个爆炸性的更好catch-all,这是痛苦多于收获。