Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/powerbi/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何在模板中存储右值或左值引用_C++_C++11_Rvalue - Fatal编程技术网

C++ 如何在模板中存储右值或左值引用

C++ 如何在模板中存储右值或左值引用,c++,c++11,rvalue,C++,C++11,Rvalue,我正在尝试创建一个简单的模板枚举器类,该类应接受定义了:运算符的任何对象,然后打印(I,v[I])形式的对。以下是一个简单的实现: template<typename T> struct enumerator { T &v; // reference to minimize copying enumerator(T &_v) : v(_v) {} void do_enumerate() { size_t i = 0;

我正在尝试创建一个简单的模板
枚举器
类,该类应接受定义了
运算符的任何对象,然后打印
(I,v[I])
形式的对。以下是一个简单的实现:

template<typename T>
struct enumerator {
    T &v; // reference to minimize copying
    enumerator(T &_v) : v(_v) {}
    void do_enumerate() {
        size_t i = 0;
        for(auto x : v) {
            cout << i << x << endl;
            i++;
        }
    }
};
构造函数来解决此错误。现在案例A不起作用,出现错误:

error: call of overloaded ‘enumerator(std::vector<int>&)’ is ambiguous
错误:重载的“枚举器(std::vector&)”的调用不明确
此外,在案例B中,枚举的输出不正确

解决这个问题最干净的方法是什么?我会的

  • 我真的希望这两种情况都能奏效
  • 不希望使用stdc以外的任何库++
  • 需要尽可能少的复制(因此在结构中只存储
    T
    不是一个选项)
  • C++11不是问题。我有g++-4.8,我认为它有足够的C++11支持

这是一个经典示例,您实际上不需要
/
结构
(它实际上引入了无用的代码),只需使用好的旧函数即可:

template<typename Container>
void enumerate(const Container& t) {
    std::size_t i = 0;
    for(auto it = t.begin(); it != t.end(); ++it, ++i)
        std::cout << i << *it << std::endl;
}
模板
无效枚举(常量容器和t){
标准:尺寸i=0;
for(auto it=t.begin();it!=t.end();++it,++i)
标准::cout

如果参数是右值,我想复制,如果不是,我不想复制。这可能吗

如图所示,这可以通过使用
make_枚举器
helper函数来实现

template <class T>
struct enumerator {
    T v;
    enumerator(T&& _v) : v(std::forward<T>(_v)) {}
    void do_enumerate() {
        size_t i = 0;
        for(auto x : v) {
            cout << i << x << endl;
            i++;
        }
    }
};

template <class T>
enumerator<T> make_enumerator(T&& x) {
    return enumerator<T>(std::forward<T>(x));
}

int main() {
    vector<int> v {5, 2, 9, 1};
    make_enumerator(v).do_enumerate();
    make_enumerator(std::move(v)).do_enumerate();
}
模板
结构枚举器{
电视
枚举数(T&&&u v):v(std::forward(_v)){
void do_enumerate(){
尺寸i=0;
用于(自动x:v){

您是否尝试过使用
T const&
T&
的构造函数?您确实意识到,一旦右值超出范围,它就会被销毁。在
枚举器
类中保留对它的引用不会改变这一点。没有
操作符
这类东西,这是基于范围的
st的语法它为
begin()
end()创建迭代器
幕后是对容器的迭代。关于如何处理它们的工作,有一些问题,请搜索它们。您试图做的是没有意义的。要么复制参数,要么不接受右值。如果参数是右值,我想复制,如果不是,我不想复制。这可能吗?Considering您的目标是避免不必要的复制,您可能应该使用
for(auto&x:v)
而不是
for(auto x:v)
。谢谢。这很有效。但是,拥有一个对象会很好,因为我计划为
枚举器
类本身定义一个迭代器接口。这样我就可以为(auto p:enumerate(whatever)){}
@subasisda是正确的,这非常有用,因为
vector
本身不支持这一点……哦wait@SubhasisDas如果您正在计划创建一个像Strut这样的范围,请考虑使用(或者至少从中吸取灵感)。。我知道boost可能具有我想要的所有功能。但是,我想让自己了解C++11中的新功能,因此这更像是一项教育工作。我将研究boost.range api。@0x499602D2如果
T
是左值引用,那么
T&
是同一类型(不是右值引用)。此外,我已经尝试过此代码。好的,我现在明白了。谢谢。很酷。这适用于所有场景。我将尝试理解
std::forward
更多信息。:)
enumerator(T _t) : t(_T) {}
error: call of overloaded ‘enumerator(std::vector<int>&)’ is ambiguous
template<typename Container>
void enumerate(const Container& t) {
    std::size_t i = 0;
    for(auto it = t.begin(); it != t.end(); ++it, ++i)
        std::cout << i << *it << std::endl;
}
enumerate(std::vector<int>{2,3,9});
template <class T>
struct enumerator {
    T v;
    enumerator(T&& _v) : v(std::forward<T>(_v)) {}
    void do_enumerate() {
        size_t i = 0;
        for(auto x : v) {
            cout << i << x << endl;
            i++;
        }
    }
};

template <class T>
enumerator<T> make_enumerator(T&& x) {
    return enumerator<T>(std::forward<T>(x));
}

int main() {
    vector<int> v {5, 2, 9, 1};
    make_enumerator(v).do_enumerate();
    make_enumerator(std::move(v)).do_enumerate();
}