c++使用constexpr函数的形参作为模板的常量

C++ use parameter of a constexpr function as constant for template

本文关键字:常量 形参 使用 constexpr 函数 c++      更新时间:2023-10-16

由于c++不允许模板类具有"auto"类型的值参数模板(您可以template<int N>template <EnumFoo E>,但您不能真正匹配两者),我想为类型+值编写一个包装器。

真正的问题是,没有人想写值和它的类型,我试着写一个函数有点类似于make_unique,除了创建一个std::unique对象,它应该有一个返回类型作为包装器。

我写的是:

enum class E1
{
  First
};
enum class E2
{
  First
};
/*
 * Here, the goal is to be able to have a ClassTemplatedOnAnyValueNoMatterType
 * you can template on E1::First, or E2::First, and the template instances
 * are NOT the same one.
 * We need a wrapper (EnumValueWrapper).
*/
template <typename T>
struct ClassTemplatedOnAnyValueNoMatterType
{};
template <typename T, T Value>
struct EnumValueWrapper
{
  static const T value = Value;
};
/*
 * Since it's annoying to write EnumValueWrapper<E1, E1::First>, we'd like to
 * have a utility function that generates the EnumValueWrapper type.
*/
template <typename T>
// does NOT compile, t outside of function body
constexpr auto makeEnumValueWrapper(const T t) -> EnumValueWrapper<T, t>;
typedef ClassTemplatedOnAnyValueNoMatterType<decltype(makeEnumValueWrapper(E1::First))> MyClass;
int main()
{
  MyClass s;
}

这不能编译,我想知道是否有任何替代方案,使用尽可能少的宏(没有MACRO(E1, First),因为我不仅希望能够使用文字,还希望能够使用int类型)。

有什么好主意吗?

这不会解决你的问题吗:

template <typename T>
struct Dummy
{
    template <T t>
    friend EnumValueWrapper<T, t> makeEnumValueWrapper();
};
template struct Dummy<E1>;
typedef ClassTemplatedOnAnyValueNoMatterType<decltype(makeEnumValueWrapper<E1::First>())> MyClass;

您仍然需要在每个相关类上显式实例化Dummy,但是MyClass的typedef没有多余的类型/值规范。

等待c++的后续迭代。

建议允许类型参数依赖于值参数的类型。到目前为止,还没有一个通过审查。

如果等待听起来不是个好主意,那就深入到标准化过程中,并自己将其添加到c++中。

在此之前,继续将template常量的类型传递给template .

我知道你不喜欢宏,但一个非常简单的解决方案是:

#define WRAP_VALUE(...) EnumValueWrapper<decltype(__VA_ARGS__), (__VA_ARGS__)>
typedef ClassTemplatedOnAnyValueNoMatterType<WRAP_VALUE(E1::First)> MyClass;

我不相信没有样板没有宏是不可能做到的。我的理由是,如果你不使用宏,你只能使用你的"值"表达式一次——要么作为函数参数,要么作为模板参数,要么作为decltype的一部分。两者单独都没有用。如果您将其用作函数参数,则无法将其值作为常量表达式检索。首先,您不能将它用作模板形参,因为没有办法声明一个接受任意类型值的模板形参——除非另一个模板形参表示该类型。最后,如果在decltype()中使用它,该值将丢失。

宏使用__VA_ARGS__而不是单个参数,以便您可以在表达式中使用逗号。例如,当作为WRAP_VALUE(std::is_same<float, bool>::value)调用时,预处理器会抱怨宏调用时带有两个参数。