c++ 我可以检查一个表达式是否依赖于类型吗?

egdjgwm8  于 11个月前  发布在  其他
关注(0)|答案(1)|浏览(99)

直觉告诉我答案是“不”,但我想我还是要问。
我想在宏中检查一个特定的表达式是否依赖于类型。下面是一个激励性的例子:

#include <concepts>
#include <format>
#include <iostream>

template <typename T>
void Print(const T &value)
{
    if constexpr (std::default_initializable<std::formatter<T>>)
        std::cout << std::format("{}", value) << '\n';
    else
        std::cout << "??\n";
}

#define PRINT(...) Print(__VA_ARGS__)

// ---

struct Unknown {};

template <typename T>
void MaybePrint(const T &value)
{
    PRINT(value);
}

int main()
{
    PRINT(42); // "42"
    PRINT(Unknown{}); // "??", but I want a build error, because the expression is not type-dependent.
    MaybePrint(42); // "42"
    MaybePrint(Unknown{}); // "??", this is ok, since the expression is type-dependent.
}

字符串
我有一个宏,可以打印传递给它的任何对象(这是一个单元测试框架)。
如果它不能打印,我显然想要一个编译错误,但是对于依赖类型的表达式,我想打印一个占位符(以避免每次都迫使用户写if constexpr (printable<T>) ...)。

vawmfj5a

vawmfj5a1#

Print的主体直接移动到宏中并调整约束,即可获得所需的行为:

#define PRINT(...)                                                     \
  {                                                                    \
    if constexpr (requires {                                           \
                    std::formatter<                                    \
                        std::remove_cvref_t<decltype(__VA_ARGS__)>>{}; \
                  })                                                   \
      std::cout << std::format("{}", __VA_ARGS__) << '\n';             \
    else                                                               \
      std::cout << "??\n";                                             \
  }

struct Unknown {};

template <typename T>
void MaybePrint(const T &value) {
  PRINT(value);
}

字符串
https://godbolt.org/z/4Po3xh9oP
我从Clang中删除了-stdlib=libc++,因为它似乎缺乏对这个例子的库支持,但是关于硬错误与替换失败的基本概念在Clang中的工作方式与GCC和MSVC中相同。
正如@SamVarshavchik所指出的,您也可以将约束移动到函数参数以获得所需的行为:

template <class T>
concept printable = std::default_initializable<std::formatter<T>>;

void Print(const printable auto &value) {
  std::cout << std::format("{}", value) << '\n';
}

struct Unknown {};

template <typename T>
void MaybePrint(const T &value) {
  if constexpr (printable<T>) {
    Print(value);
  }
}


https://godbolt.org/z/1MzWhKzrM

相关问题