我正在尝试创建一个简单的模板enumerator类,该类应该接受定义了:运算符的任何对象,然后接受(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
vector<int> v({1,2,6,2,4});
auto e = enumerator(v);
e.do_enumerate();

但是,我也希望它处理类似以下的临时对象:

案例B
auto e = enumerator(vector<int>({2,3,9});
e.do_enumerate();

这不起作用,编译器将抛出:
no matching function for call to ‘enumerator<std::vector<int> >::enumerator(std::vector<int>)

因此,我尝试添加一个
enumerator(T _t) : t(_T) {}

构造函数来解决此错误。现在,情况A不起作用,并且出现错误:
error: call of overloaded ‘enumerator(std::vector<int>&)’ is ambiguous

此外,在情况B中,枚举的输出不正确。

解决此问题的最干净方法是什么?我会
  • 非常喜欢这两种情况都可以工作
  • 建议不要使用stdc++
  • 以外的任何库
  • 想要尽可能少的复制(因此,仅将T t存储在结构中是不可选择的)
  • C++ 11没问题。我有g++-4.8,我认为它已经足够了C++ 11的支持。
  • 最佳答案



    如图所示,可以使用make_enumerator帮助器函数来完成此操作。

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

    如何运作?

    如果make_enumerator的参数是A类型的左值,则T推导为A&,我们得到枚举器enumerator<A&>,而如果它是A类型的右值,则T推导为A,我们得到枚举器enumerator<A>

    在第一种情况下,成员enumerator::v的类型将为A&,该值是绑定(bind)到构造函数参数的左值引用(不复制)。在第二种情况下,成员的类型将为Astd::forward的使用将参数_v强制转换为一个右值,因此它将在用于初始化v时从其移开。

    关于c++ - 如何在模板中存储右值或左值引用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24175279/

    10-09 13:30