预处理器命令中的 sizeof 无法编译并出现错误 C1017

sizeof in preprocessor command doesn't compile with error C1017

我想使用预处理器命令来控制代码执行路径。因为这样可以节省运行时间。

#if (sizeof(T)==1 不符合错误: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();
    }

C 和 C++ 预处理器主要是一个美化(好吧,不是那么美化)的文本替换引擎。它并不真正理解 C 或 C++ 代码。它不知道 sizeof,也不知道 C 或 C++ 类型。 (它肯定不知道模板 class 中的 T 是什么。)

如果你想在 Tsizeof 上有条件地做事,那么你需要编写 C++ 代码来完成它(即 if (...) 而不是 #if ....)

预处理器在 C++ 编译器之前运行。它对 C++ 类型一无所知;只有预处理器标记。

虽然我希望任何体面的编译器都能优化掉 if (sizeof(T) == 1),但您可以在 C++17 中使用新的 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

C++17 之前的版本不太直接。您可以使用一些 partial-specialization 恶作剧。它不是特别漂亮,我认为在这种情况下它甚至不会更有效率,但在其他情况下可以应用相同的模式:

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

在这种情况下,您可以直接特化 String,但我假设在您的实际情况下,它还有您不想重复的其他成员。

正如评论中提到的@some-programmer-dude,sizeof 不是预处理器的一部分。

如果你想让它在编译时工作,你应该使用 if constexpr

如果您不关心它是在编译时发生还是 run-time 只需使用常规 if 语句

请记住,if constexpr 是 C++17 中的新功能!

顺便说一句,Borland C++ 和 Watcom C++ 支持预处理表达式中的 sizeof(),我不知道 gcc 是否支持。