处理解除引用语法的C++泛型类

Bla*_*son 3 c++ templates generic-programming

处理某些类型需要使用成员/方法访问的事实的最佳方法是什么.操作员,而其他人使用 - >操作员.

编写代码是最好的.运算符并让调用者包装类型如下面的代码示例所示.

来自C#背景我不习惯这个特殊问题.

#include <iostream>
#include <string>
#include <vector>
#include <memory>

template<class T>
class container{
  public:
    void add(T element){
        elements_.push_back(std::move(element));   
    }

    void process(){
        for(auto& a: elements_){
            a.print();   
        }
    }
  private:
    std::vector<T> elements_;
};

class printable{
public:
    void print(){
        std::cout << "Print\n";   
    }
};

template<class T>
class printable_forwarder{
public:
    printable_forwarder(T element): element_{std::move(element)}{

    }

    void print(){
        element_->print();   
    }

private:
    T element_;
};

int main()
{
    container<printable> c1;
    c1.add(printable{});
    c1.process();

   container<printable_forwarder<std::shared_ptr<printable>>> c2;
   std::shared_ptr<printable> sp{std::make_shared<printable>()};
   c2.add(printable_forwarder<decltype(sp)>{sp});
   c2.process();
}
Run Code Online (Sandbox Code Playgroud)

这看起来更好吗?

#include <iostream>
#include <string>
#include <memory>
#include <type_traits>
#include <vector>
template<typename T>
class dereference
{
public:
    inline static T& get(T& value){
        return value;
    }
};

template<typename T>
class dereference<T*>
{
public: 
    inline static typename std::add_lvalue_reference<typename std::remove_pointer<T>::type>::type get(T* value){
        return *value;
    }
};

template<typename T>
class dereference<std::shared_ptr<T>>
{
public: 
    inline static T& get(std::shared_ptr<T> value){
        return *value.get();
    }
};

template<class T>
class container{
public:
    void add(T const& v){
        items_.push_back(v);   
    }

    void print_all(){
        for(auto& a: items_){
            dereference<T>::get(a).print();   
        }
    }
private:
    std::vector<T> items_;
};

struct printable{
    void print(){
        std::cout << "Printing\n";   
    }
};

int main()
{
    container<printable> c1;
    c1.add(printable{});
    c1.print_all();

    container<std::shared_ptr<printable>> c2;
    c2.add( std::shared_ptr<printable>(new printable{}));
    c2.print_all();
}
Run Code Online (Sandbox Code Playgroud)

Bar*_*rry 12

处理某些类型需要使用成员/方法访问的事实的最佳方法是什么.操作员,而其他人使用 - >操作员.

只是不要.

你的工作就是写作template<class T> class container.那个容器装有Ts.如果您的用户想要对其执行某些操作,则T应该展示执行某些操作的能力 - 但是他们有责任正确执行该操作.否则,你只是增加了大量的代码膨胀.太棒了,你给了我一个打印所有元素的方法,但如果我知道要调用foo()它们,或者找到第一个bar()返回大于42的元素的元素怎么办?很显然,你不会写for_each_foo()find_if_bar_is_42().

这就是标准库将容器与算法分开的原因.让你的容器,可用作可能的方式是把它公开两个iterator通过S begin()end(),然后我可以做任何我需要做的用户:

container<T> values;
values.add(...);

// I know to use '.'
for (T& t : values) {
   t.print();
} 

container<T*> pointers;
pointers.add(...);

// I know to use '->'
for (T* t : pointers) {
    t->print();
}

auto iter = std::find_if(pointers.begin(), pointers.end(), [](T* t){
    return t->bar() == 42;
});
Run Code Online (Sandbox Code Playgroud)

除此之外,您可以添加一些自己使用callables的成员函数,因此您将工作传递给用户:

template <class F>
void for_each(F&& f) {
    for (auto& elem : elements_) {
        f(elem);              // option a
        std::invoke(f, elem); // option b, as of C++17
    }
}
Run Code Online (Sandbox Code Playgroud)

所以上面的例子是:

values.for_each([](T& t){ t.print(); });
pointers.for_each([](T* t){ t->print(); });
values.for_each(std::mem_fn(&T::print));
pointers.for_each(std::mem_fn(&T::print));
Run Code Online (Sandbox Code Playgroud)

请注意,始终由用户知道该怎么做.另外,如果你std::invoke()在执行中使用for_each,那么你可以写:

pointers.for_each(&T::print);
values.for_each(&T::print);
Run Code Online (Sandbox Code Playgroud)

并且,就此而言:

container<std::unique_ptr<T>> unique_ptrs;
unique_ptrs.for_each(&T::print);
Run Code Online (Sandbox Code Playgroud)