当使用/解析模板时停止编译 [英] Stop compilation when a template has been used/resolved

查看:129
本文介绍了当使用/解析模板时停止编译的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个MCVE:

  #include  
#include< time.h>

#define MAX_LENGTH_DATETIME 25

模板< typename T>
char * convertUnixTimeToChar(time_t unixTime,T)
{
(void)unixTime;
#pragma messageconvertUnixTimeToChar()中的第二个参数必须为< char [MAX_LENGTH_DATETIME]> ;.
exit(1);
};

模板< size_t N>
char * convertUnixTimeToChar(time_t unixTime,char(& destination)[N])
{
if(N {
printf(Overflow在convertUnixTimeToChar()中:destination size [%ld]必须至少为[%u],N,MAX_LENGTH_DATETIME);
exit(1);
}
struct tm * tmNow;
tmNow = localtime(& unixTime);
strftime(目的地,MAX_LENGTH_DATETIME - 1,%Y-%m-%d%H:%M:%S,tmNow);
返回目的地;
};

int main()
{
char buffer [MAX_LENGTH_DATETIME];
printf(Converted unix time =%s\\\
,convertUnixTimeToChar(1487585045,buffer));
}

我的问题:



我想要显示消息 #pragma messageconvertUnixTimeToChar()中的第二个参数必须是< char [MAX_LENGTH_DATETIME]>类型。 类型的 char * 类型的变量传递给<$>时, c $ c> convertUnixTimeToChar()因为第一个模板已解析。现在我总是得到这个消息。



换句话说,如果传递错误的参数而不是程序运行时编译失败[在这种情况下,我必须使用 printf 而不是 #pragma 以获得通知]。



传递像 char [25] 这样的东西可以解决第二个模板,一切都很好!

有没有方式我可以有条件地停止编译错误消息,以防万一模板已被用于代码生成



使用gcc编译4.9 .4使用这些开关: -Wall -Werror -Wextra -std = c ++ 11 -O3

解决方案

再次,最佳解决方案是根本不做任何事情。

完全删除catch-all超载会导致编译器产生任何参数的错误那不能匹配 char(& destination)[N]



如果你想变得更加奇特,流n错误消息,你可以在catch-all中使用依赖的 static_assert

  template< class ...,class T> 
constexpr T&& depend(T&& o){
return std :: forward< T>(o);
}

模板< typename T>
char * convertUnixTimeToChar(time_t,T&&);
{
static_assert(取决于< T>(false),convertUnixTimeToChar()中的第二个参数必须...);
}

不是这可能不是更好的解决方案,因为你抓取了 convertUnixTimeToChar 的整个重载集合,并将其陷入一个硬错误,SFINAE会被诅咒。如果有人想为他们自己的类型添加重载,他们将不得不确保他们比这种爆炸式的捕获更好的匹配,这比收益更痛苦。


This 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 ) );
}

My question:

I would like to get displayed the message #pragma message "2nd parameter in convertUnixTimeToChar() must be of type <char [MAX_LENGTH_DATETIME]>." from gcc while the compilation only when a variable of type char * has been passed to convertUnixTimeToChar() because the 1st template was resolved. Now I get always this message.

In other words, the compilation should fail if a wrong parameter is passed and not when the program is running [in this case I have to use a printf instead of #pragma to get notified].

Passing something like char [25] resolves the 2nd template and all is fine!

Is there a way I can stop conditionally the compilation with an error message in case a template has been used physically for the code generation?

Compiled with gcc 4.9.4 using these switches: -Wall -Werror -Wextra -std=c++11 -O3

解决方案

Once more, the optimal solution is "don't do anything at all".
Removing the catch-all overload altogether will make the compiler produce an error for any parameter that cannot match char (&destination) [N].

If you want to get fancy and add your own error message, you can use a dependent static_assert inside the catch-all:

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 ...");
}

Not that this is probably not a better solution, because you grab the whole overload set for convertUnixTimeToChar and sink it into a hard error, SFINAE be damned. If someone want to add overloads for their own types, they will have to make sure theirs are a better match than this explosive catch-all, which is more pain than gain.

这篇关于当使用/解析模板时停止编译的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆