Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
366 views
in Technique[技术] by (71.8m points)

c++ - Stop compilation when a template has been used/resolved

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
", 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

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...