unspecified-bool-type

本文深入探讨了safebool技巧的起源及应用,解释了为何在C++中选择使用safebool而非直接重载bool类型。通过实例说明了如何正确地在自定义类型中实现布尔转换,避免潜在的类型转换错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

类boost::scoped_ptr的源码中有如下声明:

operator unspecified-bool-type() const;
    这是个到unspecified-bool-type类型的隐式转换函数,它可以在Boolean上下文中测试一个智能指针。如果shared_ptr保存着一个有效的指针,返回值为True;否则为false。注意,转换函数返回的类型是不确定的。把返回类型当成bool用会导致一些荒谬的操作,所以典型的实现采用了safe bool idiom,它很好地确保了只有可适用的Boolean测试可以使用。这个函数不会抛出异常。


safe bool idiom

这个就是传说中的布尔类型转换操作符号:
当我们使用if(p) 这个来检测一个p(可以是一个变量也可以是一个自己定义的类型),如果是变量很简单,如果是类型就要使用到类型的BOOL 类型转换操作符号了
safe bool idiom的起源来自于这样子的一种用法:if( obj ) { ... },对于obj是built-in类型,那自然行得通,但是对于一个class或者struct就并不总是可以了。当然可以通过这样子的用法来代替:if( obj.is_valid() ){},问题很明显,第一烦琐,第二通用性不够,也许应该使用obj.Valid()或者obj.Empty()之类的,这与template结合起来考虑是尤其是个问题。因此我们希望有一个解决方案是的我们直接可以写下if(obj)这样的语句。
初初一想,这很简单,重载operator bool不就可以了,又或者重载operator void*?是的,这两个方法确确实实使得我们可以使用if(obj)这样的语句了,但是仔细推敲的话就会发现有很多问题。
再看一个问题:
第一次看到while(cin)这种循环条件,把他改成了while(1)效果也是一样,那到底两个有什么区别呢?
while后面都是对循环的条件的检测,cin不是bool,cin是个istream类型的对象,而istream重载了operator   void*(),指针类型是可以进行判断的,0指针为false,非0为true。
至于为什么用void*而不用bool,是bool几乎可以隐式转成其它各种类型,因此容易引发各种让人奇怪的转换甚至隐藏程序错误,比如转换成char:
char   c   =   cin;
再比如:
putchar(cin);
这看上去太奇特了,所以operator   bool()不好,改用operator   void*()了。

看这里:http://www.artima.com/cppsource/safeboolP.html


参考:

http://blog.youkuaiyun.com/hityct1/article/details/3923074

http://www.cnblogs.com/hujian/archive/2012/12/10/2810754.html





static int rk_multicodecs_probe(struct platform_device *pdev) { struct snd_soc_card *card; struct device_node *np = pdev->dev.of_node; struct snd_soc_dai_link *link; struct snd_soc_dai_link_component *cpus; struct snd_soc_dai_link_component *platforms; struct snd_soc_dai_link_component *codecs; struct multicodecs_data *mc_data; struct of_phandle_args args; struct device_node *node; struct input_dev *input; u32 val; int count, value; int ret = 0, i = 0, idx = 0; const char *prefix = "rockchip,"; ret = wait_locked_card(np, &pdev->dev); if (ret < 0) { dev_err(&pdev->dev, "check_lock_card failed: %d\n", ret); return ret; } mc_data = devm_kzalloc(&pdev->dev, sizeof(*mc_data), GFP_KERNEL); if (!mc_data) return -ENOMEM; cpus = devm_kzalloc(&pdev->dev, sizeof(*cpus), GFP_KERNEL); if (!cpus) return -ENOMEM; platforms = devm_kzalloc(&pdev->dev, sizeof(*platforms), GFP_KERNEL); if (!platforms) return -ENOMEM; card = &mc_data->snd_card; card->dev = &pdev->dev; /* Parse the card name from DT */ ret = snd_soc_of_parse_card_name(card, "rockchip,card-name"); if (ret < 0) return ret; link = &mc_data->dai_link; link->name = "dailink-multicodecs"; link->stream_name = link->name; link->init = rk_dailink_init; link->ops = &rk_ops; link->cpus = cpus; link->platforms = platforms; link->num_cpus = 1; link->num_platforms = 1; link->ignore_pmdown_time = 1; card->dai_link = link; card->num_links = 1; card->dapm_widgets = mc_dapm_widgets; card->num_dapm_widgets = ARRAY_SIZE(mc_dapm_widgets); card->controls = mc_controls; card->num_controls = ARRAY_SIZE(mc_controls); card->num_aux_devs = 0; count = of_count_phandle_with_args(np, "rockchip,codec", NULL); if (count < 0) return -EINVAL; /* refine codecs, remove unavailable node */ for (i = 0; i < count; i++) { node = of_parse_phandle(np, "rockchip,codec", i); if (!node) return -ENODEV; if (of_device_is_available(node)) idx++; } if (!idx) return -ENODEV; codecs = devm_kcalloc(&pdev->dev, idx, sizeof(*codecs), GFP_KERNEL); link->codecs = codecs; link->num_codecs = idx; idx = 0; for (i = 0; i < count; i++) { node = of_parse_phandle(np, "rockchip,codec", i); if (!node) return -ENODEV; if (!of_device_is_available(node)) continue; ret = of_parse_phandle_with_fixed_args(np, "rockchip,codec", 0, i, &args); if (ret) return ret; codecs[idx].of_node = node; ret = snd_soc_get_dai_name(&args, &codecs[idx].dai_name); if (ret) return ret; idx++; } /* Only reference the codecs[0].of_node which maybe as master. */ rk_multicodecs_parse_daifmt(np, codecs[0].of_node, mc_data, prefix); link->cpus->of_node = of_parse_phandle(np, "rockchip,cpu", 0); if (!link->cpus->of_node) return -ENODEV; link->platforms->of_node = link->cpus->of_node; mc_data->mclk_fs = DEFAULT_MCLK_FS; if (!of_property_read_u32(np, "rockchip,mclk-fs", &val)) mc_data->mclk_fs = val; mc_data->mclk_adapt = 0; if (!of_property_read_u32(np, "rockchip,mclk-adapt", &val)) mc_data->mclk_adapt = val; dev_err(&pdev->dev, "%s mclk_adapt=%d\n", __func__, mc_data->mclk_adapt); mc_data->codec_hp_det = of_property_read_bool(np, "rockchip,codec-hp-det"); mc_data->adc = devm_iio_channel_get(&pdev->dev, "adc-detect"); if (IS_ERR(mc_data->adc)) { if (PTR_ERR(mc_data->adc) != -EPROBE_DEFER) { mc_data->adc = NULL; dev_warn(&pdev->dev, "Failed to get ADC channel"); } } else { if (mc_data->adc->channel->type != IIO_VOLTAGE) return -EINVAL; if (device_property_read_u32(&pdev->dev, "keyup-threshold-microvolt", &mc_data->keyup_voltage)) { dev_warn(&pdev->dev, "Invalid or missing keyup voltage\n"); return -EINVAL; } mc_data->keyup_voltage /= 1000; ret = mc_keys_load_keymap(&pdev->dev, mc_data); if (ret) return ret; input = devm_input_allocate_device(&pdev->dev); if (IS_ERR(input)) { dev_err(&pdev->dev, "failed to allocate input device\n"); return PTR_ERR(input); } input_set_drvdata(input, mc_data); input->name = "headset-keys"; input->phys = "headset-keys/input0"; input->id.bustype = BUS_HOST; input->id.vendor = 0x0001; input->id.product = 0x0001; input->id.version = 0x0100; __set_bit(EV_KEY, input->evbit); for (i = 0; i < mc_data->num_keys; i++) __set_bit(mc_data->map[i].keycode, input->keybit); if (device_property_read_bool(&pdev->dev, "autorepeat")) __set_bit(EV_REP, input->evbit); mc_data->input = input; ret = mc_keys_setup_polling(mc_data, mc_keys_poll); if (ret) { dev_err(&pdev->dev, "Unable to set up polling: %d\n", ret); return ret; } if (!device_property_read_u32(&pdev->dev, "poll-interval", &value)) mc_set_poll_interval(mc_data->poller, value); ret = input_register_device(mc_data->input); if (ret) { dev_err(&pdev->dev, "Unable to register input device: %d\n", ret); return ret; } } INIT_DEFERRABLE_WORK(&mc_data->handler, adc_jack_handler); mc_data->spk_ctl_gpio = devm_gpiod_get_optional(&pdev->dev, "spk-con", GPIOD_OUT_LOW); if (IS_ERR(mc_data->spk_ctl_gpio)) return PTR_ERR(mc_data->spk_ctl_gpio); mc_data->hp_ctl_gpio = devm_gpiod_get_optional(&pdev->dev, "hp-con", GPIOD_OUT_LOW); if (IS_ERR(mc_data->hp_ctl_gpio)) return PTR_ERR(mc_data->hp_ctl_gpio); mc_data->hp_det_gpio = devm_gpiod_get_optional(&pdev->dev, "hp-det", GPIOD_IN); if (IS_ERR(mc_data->hp_det_gpio)) return PTR_ERR(mc_data->hp_det_gpio); mc_data->extcon = devm_extcon_dev_allocate(&pdev->dev, headset_extcon_cable); if (IS_ERR(mc_data->extcon)) { dev_err(&pdev->dev, "allocate extcon failed\n"); return PTR_ERR(mc_data->extcon); } ret = devm_extcon_dev_register(&pdev->dev, mc_data->extcon); if (ret) { dev_err(&pdev->dev, "failed to register extcon: %d\n", ret); return ret; } ret = snd_soc_of_parse_audio_routing(card, "rockchip,audio-routing"); if (ret < 0) dev_warn(&pdev->dev, "Audio routing invalid/unspecified\n"); snd_soc_card_set_drvdata(card, mc_data); ret = devm_snd_soc_register_card(&pdev->dev, card); if (ret == -EPROBE_DEFER) return -EPROBE_DEFER; if (ret) { dev_err(&pdev->dev, "card register failed %d\n", ret); return ret; } platform_set_drvdata(pdev, card); return ret; }
最新发布
08-06
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值