-5

I want to use preprocessor command to control code executive path. Because in this way can save runtime time.

#if (sizeof(T)==1 doesn't comple with error: C1017

template<typename T>
    class String
    {
    public:
        static void showSize()
        {
#if (sizeof(T)==1) 
            cout << "char\n";
#else
            cout << "wchar_t\n";
#endif
        }
    };

    inline void test()
    {
        String<char>::showSize();
        String<wchar_t>::showSize();
    }
Zhang
  • 3,030
  • 2
  • 14
  • 31
  • 5
    While `sizeof` is a compile-time construct in C++, it's still not part of the preprocessor. If you want a compile-time check use `if constexpr (sizeof(T) == 1)`. – Some programmer dude Jul 03 '19 at 04:36
  • 1
    I don't suppose we can talk you into making that a formal answer, can we? – user4581301 Jul 03 '19 at 04:38
  • @user4581301, actually, you can. – Zhang Jul 03 '19 at 04:41
  • I'd expect the same code to be generated with or without `constexpr`. The compiler can deal with `if(1)` or `if(0)` and not emit a runtime choice – M.M Jul 03 '19 at 04:48
  • [How can I use "sizeof" in a preprocessor macro?](https://stackoverflow.com/questions/4079243/) [Does the sizeof operator work in preprocessor #if directives?](https://stackoverflow.com/questions/17176641/) – Remy Lebeau Jul 03 '19 at 08:35

4 Answers4

7

The preprocessor runs before the C++ compiler. It knows nothing of C++ types; only preprocessor tokens.

While I would expect any decent compiler to optimize away an if (sizeof(T) == 1), you can be explicit about it in C++17 with the new if constexpr:

template<typename T>
class String
{
public:
    static void showSize()
    {
        if constexpr (sizeof(T) == 1) {
            std::cout << "char\n";
        } else {
            std::cout << "wchar_t\n";
        }
    }
};

Live Demo

Pre C++17 it's a bit less straightforward. You could use some partial-specialization shenanigans. It's not particularly pretty, and I don't think it will even be more efficient in this case, but the same pattern could be applied in other situations:

template <typename T, size_t = sizeof(T)>
struct size_shower
{
    static void showSize()
    {
        std::cout << "wchar_t\n";
    }
};

template <typename T>
struct size_shower<T, 1>
{
    static void showSize()
    {
        std::cout << "char\n";
    }
};

template<typename T>
class String
{
public:
    static void showSize()
    {
        size_shower<T>::showSize();
    }
};

Live Demo

In this case you could directly specialize String, but I'm assuming in your real situation it has other members that you don't want to have to repeat.

Miles Budnek
  • 28,216
  • 2
  • 35
  • 52
1

The C and C++ preprocessor is mostly a glorified (well, not that glorious) text replacement engine. It doesn't really understand C or C++ code. It doesn't know sizeof, and it doesn't know C or C++ types. (It certainly won't know what T from your template class is.)

If you want to do things conditionally on T and on sizeof, then you'll need to write C++ code to do it (i.e., if (...) instead of #if ....)

jamesdlin
  • 81,374
  • 13
  • 159
  • 204
  • This will result in a completely different way. `#if` happens at compile time `if()` happens in run-time you should use `if constexpr(sizeof)` for it to work in compile time. Keep in mind that if `contsexpr if` is a new feature in C++17 – Enosh Cohen Jul 03 '19 at 04:59
  • @EnoshCohen The compiler will likely optimize it out, but it's still a good idea to mention `constexpr`. – eesiraed Jul 03 '19 at 05:00
0

As @some-programmer-dude mentioned in the comment, sizeof is not part of the preprocessor.

you should use if constexpr if you want it to work in compile time.

if you don't care if it happens in compile time or run-time just use a regular if statment

keep in mind that if constexpr is a new feature in C++17!

Enosh Cohen
  • 369
  • 2
  • 11
0

btw Borland C++ and Watcom C++ support sizeof() in preprocessor expressions, I do not know whether gcc support it.

Arnoud Mulder
  • 139
  • 1
  • 5