此访问者实现是否正确



我正在实现一个访问者,以便将其与boost变体库一起使用。我想知道用const引用类型专门化boost::static_visitor<>是否正确。

请注意,我的问题如下:

boost::static_visitor<>专门化为boost::static_visitor<const T&>有问题吗

template<typename T>
struct my_visitor : public boost::static_visitor<const T&> {
    template<typename U> const T& operator()(U& u) const {
        // some code here .....
        return X<U>::get_some_t(); // finally return some T.
    }
};

只要不返回对本地/临时的引用,就没有问题。

此外,请确保随时间检查引用的有效性(当变量对象被破坏时,即变量本身被破坏时结束,当变量被重新初始化时,(!))。

背景和解释

变体包含"当前"元素类型的对象,您可以引用到该对象中只要变量没有重新初始化为另一个元素类型(在这种情况下,引用"只是"悬空,就像引用对象的生存期结束时一样)。

因此,如果get_somet_t()返回T&T const&(或具有适当隐式转换的东西),则没有问题。

在一个更简单的设置中,让我演示有效的选项:

variant<int, std::string> v1 = 42;
int& i1 = get<int>(v1); // returns by ref, valid
i1 *= 2;
// now v1 contains the updated integer value 84

同样地,您甚至可以制作/仅引用/:的变体

std::string s = "hello";
int answer = 42;
variant<int&, std::string&> v2(s);
get<std::string&>(v2) += " world"; // now s contains "hello world"
variant<int&, std::string&> v3(answer);
get<int&>(v3) *= 2; // now `answer` contains 84

全部查看Coliru直播


演示

另一种方式,以下是好的:

struct A { std::string a_property; };
struct B { std::string b_field;    };
struct select_member : static_visitor<std::string&> {
    std::string& operator()(A& a) const { return a.a_property; }
    std::string& operator()(B& b) const { return b.b_field;    }
};
int main()
{
    variant<A,B> v = A { "some string" };
    apply_visitor(select_member(), v) += " suffix";
    std::cout << get<A>(v).a_property << "n"; // prints "some string suffix"
}

也可以在Coliru上观看。

这个怎么样,整洁吗?

public interface Worker {
  <T> T accept( Visitor<T> visitor);
}
public class Developer implements Worker { 
  @Override
  public <T> T accept( Visitor<T> visitor ) {
    return visitor.workAsDeveloper( this );
  }
}
public class Manager implements Worker {
  @Override
  public <T> T accept( Visitor<T> visitor ) {
    return visitor.manageAsManager( this );
  }
}
public class Boss implements Worker {  
  @Override
  public <T> T accept( Visitor<T> visitor ) {
    return visitor.planLikeBoss( this );
  }
}
public interface Visitor<T> {
  T workAsDeveloper( Developer type );
  T manageAsManager( Manager type );
  T planLikeBoss( Boss type );
}
public class VisitorImpl implements Visitor<String> {
  
  @Override
  public String workAsDeveloper( Developer type ) {
    return "Working hard as a Developer";
  }
  
  @Override
  public String manageAsManager( Manager type ) {
    return "Managing smoothly as a Manager";
  }
  
  @Override
  public String planLikeBoss( Boss type ) {
    return "Planning like a Boss";
  }
}
public class App {
  Visitor<String> visitor;
  
  public App( Visitor<String> visitor ) {
    this.visitor = visitor;
  }
  
  public static void main( String[] args ) {
    // Given
    App app = new App( new VisitorImpl() );
    
    Developer developer = new Developer();
    Manager manager = new Manager();
    Boss boss = new Boss();
    
    // When
    app.run( developer );
    app.run( manager );
    app.run( boss );
  }
  
  void run( Worker worker ) {
    System.out.println( worker.accept( visitor ) );
  }
}

相关内容

  • 没有找到相关文章

最新更新