我想用一个boost.variant<T0,T1,T2>作为参数传递到模板"访问者"类,它会为游客提供运营商所要求的boost.variant游客机制,在这种情况下,所有返回void即
void operator()(T0 value);
void operator()(T1 value);
void operator()(T2 value);
Run Code Online (Sandbox Code Playgroud)
该模板还将为变体中的每个类型T0 ...具有相应的虚函数,该函数默认不执行任何操作.用户可以从模板类继承并仅重新定义他感兴趣的虚拟函数.这类似于众所周知的"模板方法"模式.我能够想出的唯一解决方案是将boost :: variant和关联的访问者包装在一个模板中,并通过typedef访问它们.这没关系,但感觉有点笨重.这是代码:
#include "boost/variant.hpp"
//create specializations of VariantWrapper for different numbers of variants -
//just show a template for a variant with three types here.
//variadic template parameter list would be even better!
template<typename T0, typename T1, typename T2>
struct VariantWrapper
{
//the type for the variant
typedef boost::variant<T0,T1,T2> VariantType;
//The visitor class for this variant
struct Visitor : public boost::static_visitor<>
{
void operator()(T0 value)
{ …Run Code Online (Sandbox Code Playgroud) 为每个原始值都有一个包装器很好,所以没有办法滥用它.我怀疑这种便利是有代价的.性能下降了吗?如果性能受到关注,我是否应该使用裸原始值?
我达到了50种类型的极限boost::variant.我发现这个漂亮的自包含标题,但它缺乏多访问功能(我实际上需要双重访问).
我试着看一下它,但这种方法似乎非常雄心勃勃,与我缺乏元编程经验相冲突......
如果你可以指出一个预先制作的变体实现或者提供一些建议来扩展我喜欢的那个,那将是非常好的,谢谢!
ToFilipRoséen和upvoters:在这里您可以找到我正在考虑的设计的基本示例.随意添加更多关于此的深入评论.
下面的代码:
int i = 1;
const int i_c = 2;
volatile int i_v = 3;
const volatile int i_cv = 4;
typedef std::variant<int, const int, volatile int, const volatile int> TVariant;
TVariant var (i );
TVariant var_c (i_c );
TVariant var_v (i_v );
TVariant var_cv(i_cv);
std::cerr << std::boolalpha;
std::cerr << std::holds_alternative< int>(var ) << std::endl;
std::cerr << std::holds_alternative<const int>(var_c ) << std::endl;
std::cerr << std::holds_alternative< volatile int>(var_v ) << std::endl;
std::cerr << std::holds_alternative<const volatile int>(var_cv) << std::endl;
std::cerr << var …Run Code Online (Sandbox Code Playgroud) 好的,所以我真的不能想到一个总结这个的apropos标题.
IPrintPipelinePropertyBag接口具有AddProperty方法,该方法恰当地"将属性添加到属性包".
http://msdn.microsoft.com/en-us/library/aa506384.aspx
AddProperty([in,string] const wchar_t*pszName,[in] const VARIANT*pVar);
我们使用以下代码将字符串添加到属性包中.
CComVariant varProperty = CComBSTR(someString);
pPrintPropertyBag->AddProperty(L"SOME_PROPERTY", &varFilename);
Run Code Online (Sandbox Code Playgroud)
但是很明显,创建的CComBSTR和CComVariant在一段时间后超出了范围.我不确定PropertyBag是否处理字符串并制作自己的副本.由于我们可以在VARIANT中存储各种内容,因此情况并非如此.
假设没有处理字符串,我的问题是,在COM中执行此操作的模式是什么?我应该如何传递包含已分配字符串的VARIANT,使该字符串可用于其他线程,即使调用AddProperty的线程首先死亡,并正确地取消分配字符串?
我希望建模一个可以有两种可能形式的值:缺席或字符串.
执行此操作的自然方式是with Maybe String,or Optional<String>,or string option等.但是,Go没有这样的变体类型.
然后我想,在Java,C等之后,替代方案将是可空性,或者nil在Go中.但是,nil不是stringGo 中的类型成员.
搜索,然后我想使用该类型*string.这可能有效,但看起来很尴尬(例如,我不能采用字符串文字的地址,就像我可以获取结构文字的地址一样).
在Go中模拟这样一个值的惯用方法是什么?
发明一个有区别的联合/标记变体我得出结论,在编译时"在一些条件下使析构函数变得微不足道"这样的特性需要特别需要.我的意思是某种SFINAE或类似的东西(伪代码):
template< typename ...types >
struct X
{
~X() = default((std::is_trivially_destructible< types >{} && ...))
{
// non-trivial code here
}
};
Run Code Online (Sandbox Code Playgroud)
这意味着如果条件default(*)为true,则析构函数的定义等于~X() = default;,但如果是false则{ // ... }使用body来代替.
#pragma once
#include <type_traits>
#include <utility>
#include <experimental/optional>
#include <cassert>
template< typename ...types >
class U;
template<>
class U<>
{
U() = delete;
U(U &) = delete;
U(U const &) = delete;
U(U &&) = delete;
U(U const …Run Code Online (Sandbox Code Playgroud) 可能我不是第一个发现std::exception_ptr可以用来实现any类型的人(性能考虑被放在一边),因为它可能是C++中唯一可以容纳任何东西的类型.然而,谷歌搜索没有带来任何这方面的结果.
有没有人知道以下方法是否曾用于任何有用的方法?
#include <exception>
#include <iostream>
struct WrongTypeError : std::exception { };
class Any {
public:
template <class T>
void set (T t) {
try { throw t; }
catch (...) { m_contained = std::current_exception(); }
}
template <class T>
T const & get () {
try { std::rethrow_exception (m_contained); }
catch (T const & t) { return t; }
catch (...) { throw WrongTypeError {}; }
}
private:
std::exception_ptr m_contained = nullptr;
};
int main …Run Code Online (Sandbox Code Playgroud) 当人们已经知道某些需要动态多态性的代码中涉及的所有有限数量的类型时,与 usingenum相比,using 的性能会更好,Box因为后者使用动态内存分配,并且您需要使用具有虚拟函数调用的特征对象出色地。
也就是说,与使用std::variantand的 C++ 中的等效代码相比std::visit,在这种情况下,Rust 看起来涉及更多样板代码,至少对我来说是这样(我还没有学会使用过程宏)。在这里举一些例子:我有很多struct类型:
struct A {
// ...
}
struct B {
// ...
}
// ...
struct Z {
// ...
}
Run Code Online (Sandbox Code Playgroud)
他们都实现了AlphabetLetter以下特征:
trait AlphabetLetter {
fn some_function(&self);
}
Run Code Online (Sandbox Code Playgroud)
由于涉及的类型集是已知且有限的,我想使用enum:
enum Letter {
AVariant(A),
BVariant(B),
// ...
ZVariant(Z),
}
Run Code Online (Sandbox Code Playgroud)
这里我们已经有了第一个样板:我需要为enum涉及的每个类型变体的值添加一个名称。但真正的问题是:enum Letter它本身就是一个AlphabetLetter,它只是代表了这样一个事实:我们在运行时不知道它是哪个字母。所以我开始为它实现这个特质:
impl AlphabetLetter for Letter {
fn some_function(&self) {
match self {
Letter::AVariant(letter) => letter.some_function(); …Run Code Online (Sandbox Code Playgroud)