C++ 是否可以有一个“自动”成员变量?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18199728/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 21:48:13  来源:igfitidea点击:

Is it possible to have an "auto" member variable?

c++structauto

提问by Oleksiy

For example I wanted to have a variable of type autobecause I'm not sure what type it will be.

例如,我想要一个类型的变量,auto因为我不确定它将是什么类型。

When I try to declare it in class/struct declaration it's giving me this error:

当我尝试在类/结构声明中声明它时,它给了我这个错误:

Cannot deduce auto type. Initializer required

无法推断自动类型。需要初始化程序

Is there a way around it?

有办法解决吗?

struct Timer {

    auto start;

};

回答by Mark Garcia

You can, but you have to declare it staticand const:

你可以,但你必须声明它static并且const

struct Timer {
    static const auto start = 0;
};

A working example in Coliru.

Coliru 中的一个工作示例

With this limitation, you therefore cannot have startas a non-static member, and cannot have different values in different objects.

由于此限制,因此您不能将其start作为非静态成员,并且不能在不同的对象中具有不同的值。

If you want different types of startfor different objects, better have your class as a template

如果您想要不同start对象的不同类型,最好将您的类作为模板

template<typename T>
struct Timer {
    T start;
};

If you want to deduce the type of T, you can make a factory-like function that does the type deduction.

如果你想推导 的类型T,你可以制作一个类似工厂的函数来进行类型推导。

template<typename T>
Timer<typename std::decay<T>::type> MakeTimer(T&& startVal) {   // Forwards the parameter
   return Timer<typename std::decay<T>::type>{std::forward<T>(startVal)};
}

Live example.

活生生的例子

回答by Shafik Yaghmour

This is what the C++ draft standardhas to say about using autofor member variables, in section 7.1.6.4 auto specifierparagraph 4:

这就是C++ 草案标准关于使用auto成员变量的说法,在章节7.1.6.4 auto specifier段落中4

The auto type-specifier can also be used in declaring a variable in the condition of a selection statement (6.4) or an iteration statement (6.5), in the type-specifier-seq in the new-type-id or type-id of a new-expression (5.3.4), in a for-range-declaration, and in declaring a static data member with a brace-or-equal-initializer that appears within the member-specification of a class definition (9.4.2).

auto 类型说明符也可用于在选择语句 (6.4) 或迭代语句 (6.5) 的条件中声明变量,在 new-type-id 或 type-id 的 type-specifier-seq 中new 表达式 (5.3.4),在 for-range-declaration 中,以及在声明一个静态数据成员时,该静态数据成员出现在类定义 (9.4.2) 的成员规范中.

Since it must be initialized this also means that it must be const. So something like the following will work:

由于它必须被初始化,这也意味着它必须是const. 因此,类似以下内容将起作用:

struct Timer
{
  const static int start = 1;
}; 

I don't think that gets you too much though. Using template as Mark suggests or now that I think about it some more maybe you just need a variant type. In that case you should check out Boost.Variantor Boost.Any.

不过,我认为这不会让你太过分。按照 Mark 的建议使用模板,或者现在我再考虑一下,也许您只需要一个变体类型。在这种情况下,您应该查看Boost.VariantBoost.Any

回答by MSalters

No. Each constructor could have its own initializer for start, so there could be no consistent type to use.

不。每个构造函数都可以有自己的 初始化器start,因此可能没有一致的类型可供使用。

If you dohave a usable expression, you can use that:

如果您确实有可用的表达式,则可以使用它:

struct Timer {

   Foo getAFoo();

   delctype(Timer().getAFoo().Bar()) start;

   Timer() : start(getAFoo().Bar()) { /***/ }
};

回答by David Ledger

Indirectly, provided that you don't reference a member of the class.

间接地,前提是您不引用类的成员。

This can also now be achieved through deduction guides, these were introduced in C++17 and have recently (finally) support in VC++ has been added (clang and GCC already had it).

这现在也可以通过推导指南来实现,这些指南是在 C++17 中引入的,并且最近(最终)添加了 VC++ 支持(clang 和 GCC 已经有了它)。

https://en.cppreference.com/w/cpp/language/class_template_argument_deduction

https://en.cppreference.com/w/cpp/language/class_template_argument_deduction

For example:

例如:

template <typename>
struct CString;

template <typename T, unsigned N>
struct CString<std::array<T, N>>
{
    std::array<T, N> const Label;

    CString(std::array<T, N> const & pInput) : Label(pInput) {}
};

template <typename T, std::size_t N>
CString(std::array<T, N> const & pInput) -> CString<std::array<T, N>>;

https://godbolt.org/z/LyL7UW

https://godbolt.org/z/LyL7UW

This can be used to deduce class member types in a similar manner to auto. Although the member variables need to be Dependant somehow on the constructor arguments.

这可用于以与 auto 类似的方式推断类成员类型。尽管成员变量需要以某种方式依赖于构造函数参数。