error C2131: 使用 constexpr 时表达式未计算为常量

error C2131: expression did not evaluate to a constant when using constexpr

我尝试编写三种类型的元编程模板来检查 class 对象是否能够转换为 int。

#include <iostream>
using namespace std;

template<typename T>
struct meta1
{
    static char(&resolve(int))[2];
    static char resolve(...);
    enum { value = sizeof(resolve(T())) - 1 };
};

template<typename T>
struct meta2
{
    struct result_yes { char _[2]; };
    typedef char result_no;
    static result_yes resolve(int);
    static result_no resolve(...);
    enum { value = sizeof(resolve(T())) - 1 };
};

template<typename T>
struct meta3
{
    static constexpr bool resolve(int) { return true; }
    static constexpr bool resolve(...) { return false; }
    enum { value = resolve(T()) }; // error C2131: expression did not evaluate to a constant
};

#define CHECK(FUNC_NAME) \
cout << "Checking " #FUNC_NAME << endl; \
cout << FUNC_NAME<int>::value << endl; \
cout << FUNC_NAME<string>::value << endl; \

int main()
{
    CHECK(meta1)
    CHECK(meta2)
    CHECK(meta3)
}

并且在使用constexpr时出现错误, error C2131: 表达式未计算为常量 我该如何解决这个问题,为什么会这样?

谢谢。

不确定为什么这不像在其他情况下那样工作,但作为解决方法,您可以将 meta3 变成

template<typename T>
struct meta3
{
    enum { value = std::is_same_v<T, int> };
};

它将使用 C++17 或更高版本进行编译。如果你想支持 C++11 或 C++14,你可以使用 std::is_same<T, int>::value

constexpr 标记的函数实际上不需要在编译时调用。它们可以,但如果它们的参数是运行时的东西,它们也可以在运行时工作。在您的情况下,std::string 在编译时不适用于 result(因为 std::string 无法在编译时求值 - 没有 constexpr 构造函数)。

int 可以做到这一点。

其他方法工作得很好,因为它们不使用 constexpr 函数

编辑:您也许可以从 std::declval 中受益,而不是使用 T() link

EDIT2:这不是 an option 还是出于学习目的?