简体   繁体   English

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

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

Since C++ does not allow template class with a value parameter template of "auto" type (you can template<int N> , or template <EnumFoo E> , but you cannot really match both), I wanted to write a wrapper for a type+value. 由于C ++不允许使用带有“自动”类型的值参数模板的模板类(您可以template<int N>template <EnumFoo E> ,但是不能真正将两者都匹配),所以我想为该类型编写包装器+值。

The real problem is, no one wants to write both value and its type, and I tried to write a function a bit similar with make_unique , except that creating a std::unique object, it was supposed to have a return type being the wrapper. 真正的问题是,没有人想同时写值和它的类型,我试图写一个与make_unique有点类似的函数,除了创建一个std::unique对象,它应该有一个返回类型是包装器。 。

Here is what I wrote: 这是我写的:

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;
}

This does not compile, and I'd like to know if there are any alternatives, using as few macros as possible (no MACRO(E1, First) , since I'd like to be able to use not only litterals, and would like to be able to use int type too). 这不会编译,我想知道是否有其他选择,请使用尽可能少的宏(不使用MACRO(E1, First) ,因为我不仅希望使用乱抛垃圾,而且希望也可以使用int类型)。

Got any ideas to do that? 有任何想法可以做到吗?

Wait for a later iteration of C++. 等待C ++的后续迭代。

Proposals to allow type parameters to depend on the type of value parameters have been proposed. 已经提出了允许类型参数依赖于值参数类型的建议。 As yet, none have managed to pass muster. 到目前为止,还没有人设法通过要求。

If waiting doesn't sound like a good idea, dive into the standardization process and add it to C++ yourself. 如果听起来不是一个好主意,请深入标准化过程,然后将其自己添加到C ++中。

Until then, continue to pass the type of your template constants into the template . 在此之前,继续将template常量的类型传递给template

I know you don't like macros, but a very simple solution is: 我知道您不喜欢宏,但是一个非常简单的解决方案是:

#define WRAP_VALUE(...) EnumValueWrapper<decltype(__VA_ARGS__), (__VA_ARGS__)>

typedef ClassTemplatedOnAnyValueNoMatterType<WRAP_VALUE(E1::First)> MyClass;

I don't believe it's possible to do it without boilerplate without macros. 我不相信没有宏就没有样板也是不可能的。 My reasoning is that if you don't use a macro, you can only use your "value" expression once - either as a function argument, a template parameter, or as part of decltype. 我的理由是,如果不使用宏,则只能使用一次“值”表达式-作为函数参数,模板参数或decltype的一部分。 And neither alone is useful. 而且没有一个是有用的。 If you use it as a function argument, you can't retrieve its value as a constant expression. 如果将其用作函数参数,则无法将其值检索为常量表达式。 You can't use it as a template parameter in the first place, since there is no way to declare a template parameter that will accept a value of arbitrary type - not without another template parameter representing that type. 首先,您不能将其用作模板参数,因为无法声明将接受任意类型值的模板参数-除非没有另一个代表该类型的模板参数。 And finally, if you use it within decltype(), the value will be lost. 最后,如果在decltype()中使用它,则该值将丢失。

The macro is using __VA_ARGS__ instead of a single argument so that you can use commas within the expression. 宏使用__VA_ARGS__而不是单个参数,因此您可以在表达式中使用逗号。 For example, when invoked as WRAP_VALUE(std::is_same<float, bool>::value) , the preprocessor would otherwise complain that the macro is called with two arguments. 例如,当以WRAP_VALUE(std::is_same<float, bool>::value)调用时,预处理器会抱怨该宏被调用时带有两个参数。

wouldn't this work for your problem: 这不适用于您的问题:

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

you still need the explicit instantiation of the Dummy on each of the relevant classes, but the typedef for MyClass is free of redundant type/value specification. 您仍然需要在每个相关类上显式实例化Dummy,但是MyClass的typedef没有多余的类型/值规范。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM