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

时间:2014-06-06 18:28:18

标签: c++ templates constexpr

由于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),因为我希望不仅能够使用litterals,而且我希望能够使用int类型。

有任何想法吗?

3 个答案:

答案 0 :(得分:0)

等待稍后的C ++迭代。

已经提出了允许类型参数取决于值参数类型的提议。到目前为止,还没有人能够通过集合。

如果等待并不是一个好主意,请深入了解标准化过程并自行将其添加到C ++中。

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

答案 1 :(得分:0)

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

#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)时,预处理器会抱怨用两个参数调用宏。

答案 2 :(得分:0)

这不适用于您的问题:

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没有冗余类型/值规范。