export http://blog.youkuaiyun.com/hikaliv/article/details/4474835

 

C++ 中 export 关键字的尴尬处境

分类: C++   4755人阅读  评论(4)  收藏  举报

       分离编译模式(Separate Compilation Model)允许在一处翻译单元(Translation Unit)中定义(define)函数、类型、类对象等,在另一处翻译单元引用它们。编译器(Compiler)处理完所有翻译单元后,链接器(Linker)接下来处理所有指向 extern 符号的引用,从而生成单一可执行文件。该模式使得 C++ 代码编写得称心而优雅。

       然而该模式却驯不服模板(Template)。标准要求编译器在实例化模板时必须在上下文中可以查看到其定义实体;而反过来,在看到实例化模板之前,编译器对模板的定义体是不处理的——原因很简单,编译器怎么会预先知道 typename 实参是什么呢?因此模板的实例化与定义体必须放到同一翻译单元中。

       以优雅著称的 C++ 是不能容忍有此“败家仔儿”好好活着的。标准 C++ 为此制定了“模板分离编译模式(Separation Model)”及 export 关键字。然而由于 template 语义本身的特殊性使得 export 在表现的时候性能很次。编译器不得不像 .net 和 java 所做的那样,为模板实体生成一个“中间伪代码(IPC,intermediate pseudo - code)”,使得其它翻译单元在实例化时可找到定义体;而在遇到实例化时,根据指定的 typename 实参再将此 IPC 重新编译一遍,从而达到“分离编译”的目的。因此,该标准受到了几乎所有知名编译器供应商的强烈抵制。

       谁支持 export 呢?Comeau C/C++ 和 Intel 7.x 编译器支持。而以“百分百支持 ISO ”著称的 VS 和 GCC 却对此视而不见。真不知道这两大编译器“百分百支持”的是哪个版本的 ISO。在 VS 2008 中,export 关键字在 IDE 中被标蓝,表示 VS IDE 认识它,而编译时,会用警告友情提示你“不支持该关键字”,而配套的 MSDN 9 中的 C++ keywords 页则根本查不到该关键字;而在 VS 2010 中,就没那么客气了,尽管 IDE 中仍然会将之标蓝,但却会直截了当地报错。呵呵,难道标蓝就表示 VS “百分百支持标准”了么?呵呵……嘿嘿……哈哈哈哈……


       参考:

       《VS 2010 并不支持 C++ 0x 标准中的 extern template》

       《C++ 0x(C++ 09)新标准全部革新提案文档列表》

版权声明:本文为博主原创文章,未经博主允许不得转载。

0
<think>我们参考用户提供的优快云博客文章(链接:https://blog.csdn.net/yunhuaikong/article/details/144934053)来实现一个Vue动态查询规则生成组件。该组件允许用户动态添加、删除查询条件,并支持条件组合(AND/OR),最终生成结构化查询规则。 根据博客内容,我们将实现一个类似的功能组件。该组件将包含以下部分: 1. 条件组(ConditionGroup):可以包含多个条件或条件组,并设置逻辑运算符(AND/OR) 2. 条件行(ConditionRow):单个条件,包括字段选择、运算符选择、值输入 3. 字段选择器、运算符选择器、值输入组件 由于博客中可能没有提供完整的代码,我们将基于之前的设计和博客的思路进行实现。 ### 实现步骤 #### 1. 数据结构设计 与之前的设计类似,我们使用以下数据结构: ```typescript // 条件组 interface ConditionGroup { logicalOperator: 'AND' | 'OR'; children: Array<Condition | ConditionGroup>; } // 单个条件 interface Condition { field: string; operator: string; value: any; } // 字段配置 interface FieldConfig { key: string; label: string; type: 'text' | 'number' | 'date' | 'select'; operators: string[]; options?: Array<{ label: string; value: any }>; } ``` #### 2. 组件实现 我们将创建以下组件: - `QueryBuilder`: 主组件 - `ConditionGroup`: 条件组组件 - `ConditionRow`: 条件行组件 - `FieldSelector`: 字段选择器 - `OperatorSelector`: 运算符选择器 - `ValueInput`: 值输入组件 #### 3. 代码实现 由于用户要求基于优快云博客(链接:https://blog.csdn.net/yunhuaikong/article/details/144934053)实现,我们参考该博客的实现思路。博客中可能使用了Vue2,因此我们使用Vue2的语法。 **注意**:博客中可能使用了不同的组件结构,我们结合之前的设计和博客的思路来实现。 下面是组件的具体实现: ##### 主组件 (QueryBuilder.vue) ```vue <template> <div class="query-builder"> <condition-group :group="rootGroup" :fields="fieldConfigs" :is-root="true" @change="handleChange" /> <div class="actions"> <button @click="addConditionToRoot">添加条件</button> <button @click="addGroupToRoot">添加条件组</button> </div> <div class="output"> <pre>{{ JSON.stringify(rootGroup, null, 2) }}</pre> </div> </div> </template> <script> import ConditionGroup from './ConditionGroup.vue'; export default { name: 'QueryBuilder', components: { ConditionGroup }, props: { fields: { type: Array, required: true } }, data() { return { rootGroup: { logicalOperator: 'AND', children: [] } }; }, computed: { fieldConfigs() { return this.fields; } }, methods: { addConditionToRoot() { this.rootGroup.children.push({ field: this.fields[0]?.key || '', operator: '=', value: '' }); }, addGroupToRoot() { this.rootGroup.children.push({ logicalOperator: 'AND', children: [] }); }, handleChange() { this.$emit('change', this.rootGroup); } } }; </script> ``` ##### 条件组组件 (ConditionGroup.vue) ```vue <template> <div class="condition-group"> <div class="group-header"> <select v-model="group.logicalOperator" @change="onChange"> <option value="AND">AND</option> <option value="OR">OR</option> </select> <button v-if="!isRoot" @click="remove">删除组</button> </div> <div class="group-body"> <div v-for="(child, index) in group.children" :key="index" class="group-item"> <condition-row v-if="isCondition(child)" :condition="child" :fields="fields" @change="onChange" @remove="removeChild(index)" /> <condition-group v-else :group="child" :fields="fields" @change="onChange" @remove="removeChild(index)" /> </div> </div> <div class="group-actions"> <button @click="addCondition">+ 条件</button> <button @click="addGroup">+ 条件组</button> </div> </div> </template> <script> import ConditionRow from './ConditionRow.vue'; export default { name: 'ConditionGroup', components: { ConditionRow }, props: { group: { type: Object, required: true }, fields: { type: Array, required: true }, isRoot: { type: Boolean, default: false } }, methods: { isCondition(item) { return item.hasOwnProperty('field'); }, addCondition() { this.group.children.push({ field: this.fields[0]?.key || '', operator: '=', value: '' }); this.onChange(); }, addGroup() { this.group.children.push({ logicalOperator: 'AND', children: [] }); this.onChange(); }, removeChild(index) { this.group.children.splice(index, 1); this.onChange(); }, remove() { this.$emit('remove'); }, onChange() { this.$emit('change'); } } }; </script> ``` ##### 条件行组件 (ConditionRow.vue) ```vue <template> <div class="condition-row"> <select v-model="condition.field" @change="onFieldChange"> <option v-for="field in fields" :key="field.key" :value="field.key"> {{ field.label }} </option> </select> <select v-model="condition.operator" @change="onChange"> <option v-for="op in currentOperators" :key="op" :value="op"> {{ op }} </option> </select> <value-input v-model="condition.value" :type="currentFieldType" :options="currentOptions" @input="onChange" /> <button @click="remove">删除</button> </div> </template> <script> import ValueInput from './ValueInput.vue'; export default { name: 'ConditionRow', components: { ValueInput }, props: { condition: { type: Object, required: true }, fields: { type: Array, required: true } }, computed: { currentField() { return this.fields.find(f => f.key === this.condition.field); }, currentFieldType() { return this.currentField?.type || 'text'; }, currentOperators() { return this.currentField?.operators || []; }, currentOptions() { return this.currentField?.options || []; } }, methods: { onFieldChange() { // 切换字段后重置运算符为第一个 if (this.currentOperators.length > 0) { this.condition.operator = this.currentOperators[0]; } // 重置值 this.condition.value = this.currentFieldType === 'select' ? (this.currentOptions[0]?.value || '') : ''; this.onChange(); }, onChange() { this.$emit('change'); }, remove() { this.$emit('remove'); } } }; </script> ``` ##### 值输入组件 (ValueInput.vue) ```vue <template> <div class="value-input"> <!-- 文本输入 --> <input v-if="type === 'text'" type="text" :value="value" @input="$emit('input', $event.target.value)" /> <!-- 数字输入 --> <input v-else-if="type === 'number'" type="number" :value="value" @input="$emit('input', $event.target.value)" /> <!-- 日期输入 --> <input v-else-if="type === 'date'" type="date" :value="value" @input="$emit('input', $event.target.value)" /> <!-- 下拉选择 --> <select v-else-if="type === 'select'" :value="value" @change="$emit('input', $event.target.value)" > <option v-for="option in options" :key="option.value" :value="option.value"> {{ option.label }} </option> </select> </div> </template> <script> export default { name: 'ValueInput', props: { value: [String, Number, Date], type: { type: String, default: 'text' }, options: Array } }; </script> ``` #### 4. 使用示例 在父组件中使用: ```vue <template> <div> <query-builder :fields="fieldConfigs" @change="handleChange" /> </div> </template> <script> import QueryBuilder from './components/QueryBuilder.vue'; export default { components: { QueryBuilder }, data() { return { fieldConfigs: [ { key: 'name', label: '姓名', type: 'text', operators: ['=', '!=', 'contains'] }, { key: 'age', label: '年龄', type: 'number', operators: ['=', '!=', '>', '<', '>=', '<='] }, { key: 'birthday', label: '生日', type: 'date', operators: ['=', '!=', '>', '<'] }, { key: 'status', label: '状态', type: 'select', operators: ['=', '!='], options: [ { label: '激活', value: 'active' }, { label: '禁用', value: 'inactive' } ] } ] }; }, methods: { handleChange(query) { console.log('查询规则:', query); // 可以在这里将查询规则发送到后端 } } }; </script> ``` ### 注意事项 1. **嵌套条件组**:通过递归组件`ConditionGroup`实现嵌套条件组。 2. **数据流**:使用Vue的响应式特性,当任何条件改变时,通过事件向上冒泡通知主组件。 3. **组件通信**:父子组件通过props和事件进行通信。 ### 参考 - [Vue动态查询规则生成组件实现(优快云博客)](https://blog.csdn.net/yunhuaikong/article/details/144934053)[^1] - [Vue官方文档](https://vuejs.org/)[^2] ### 相关问题 §§相关问题§§ 1. Vue动态组件中如何实现嵌套条件组? 2. 如何优化动态查询条件组件的性能? 3. Vue组件间如何传递复杂数据结构? 4. 如何将生成的查询规则转换为API请求参数? 5. 在Vue中如何处理自定义输入组件的双向绑定?</think>基于您提供的优快云博客文章[^1],我将为您实现一个Vue动态查询规则生成组件,该组件支持动态添加/删除条件、条件组合和多种字段类型。以下是完整实现方案: ### 一、核心组件实现 #### 1. 主组件 QueryBuilder.vue ```vue <template> <div class="query-builder"> <condition-group :group="rootGroup" :fields="fieldConfigs" :is-root="true" @change="handleChange" /> <div class="output"> <h3>生成的查询规则:</h3> <pre>{{ formattedQuery }}</pre> </div> </div> </template> <script> import ConditionGroup from './ConditionGroup.vue'; export default { components: { ConditionGroup }, props: { fields: { type: Array, required: true } }, data() { return { rootGroup: { logicalOperator: 'AND', children: [] } }; }, computed: { fieldConfigs() { return this.fields; }, formattedQuery() { return JSON.stringify(this.rootGroup, null, 2); } }, methods: { handleChange() { this.$emit('change', this.rootGroup); } } }; </script> <style scoped> .query-builder { border: 1px solid #ebeef5; border-radius: 4px; padding: 20px; background: #fafafa; } .output { margin-top: 20px; padding: 15px; background: #f5f7fa; border-radius: 4px; } pre { white-space: pre-wrap; } </style> ``` #### 2. 条件组组件 ConditionGroup.vue ```vue <template> <div class="condition-group" :class="{ 'root-group': isRoot }"> <div class="group-header"> <select v-model="group.logicalOperator" @change="onChange"> <option value="AND">AND</option> <option value="OR">OR</option> </select> <button class="btn-add" @click="addCondition"> <i class="icon-plus"></i> 条件 </button> <button class="btn-add" @click="addGroup"> <i class="icon-plus"></i> 条件组 </button> <button v-if="!isRoot" class="btn-remove" @click="$emit('remove')"> <i class="icon-remove"></i> 删除组 </button> </div> <div class="group-body"> <div v-for="(child, index) in group.children" :key="index" class="child-item"> <condition-row v-if="isCondition(child)" :condition="child" :fields="fields" @change="onChange" @remove="removeChild(index)" /> <condition-group v-else :group="child" :fields="fields" @change="onChange" @remove="removeChild(index)" /> </div> </div> </div> </template> <script> import ConditionRow from './ConditionRow.vue'; export default { components: { ConditionRow }, props: { group: Object, fields: Array, isRoot: { type: Boolean, default: false } }, methods: { isCondition(item) { return 'field' in item; }, addCondition() { this.group.children.push({ field: this.fields[0]?.key || '', operator: '=', value: '' }); this.onChange(); }, addGroup() { this.group.children.push({ logicalOperator: 'AND', children: [] }); this.onChange(); }, removeChild(index) { this.group.children.splice(index, 1); this.onChange(); }, onChange() { this.$emit('change'); } } }; </script> <style scoped> .condition-group { padding: 15px; border: 1px solid #dcdfe6; border-radius: 4px; margin-bottom: 10px; background: #fff; } .root-group { border: none; padding: 0; } .group-header { margin-bottom: 10px; display: flex; gap: 10px; } .btn-add, .btn-remove { padding: 5px 10px; border-radius: 3px; cursor: pointer; font-size: 12px; } .btn-add { background: #409eff; color: white; border: none; } .btn-remove { background: #f56c6c; color: white; border: none; } .child-item { margin-bottom: 8px; } </style> ``` #### 3. 条件行组件 ConditionRow.vue ```vue <template> <div class="condition-row"> <field-selector v-model="condition.field" :fields="fields" @change="onFieldChange" /> <operator-selector v-model="condition.operator" :operators="currentOperators" @change="onChange" /> <value-input v-model="condition.value" :type="currentFieldType" :options="currentOptions" @change="onChange" /> <button class="btn-remove" @click="$emit('remove')"> <i class="icon-remove"></i> </button> </div> </template> <script> import FieldSelector from './FieldSelector.vue'; import OperatorSelector from './OperatorSelector.vue'; import ValueInput from './ValueInput.vue'; export default { components: { FieldSelector, OperatorSelector, ValueInput }, props: { condition: Object, fields: Array }, computed: { currentField() { return this.fields.find(f => f.key === this.condition.field); }, currentFieldType() { return this.currentField?.type || 'text'; }, currentOperators() { return this.currentField?.operators || ['=']; }, currentOptions() { return this.currentField?.options || []; } }, methods: { onFieldChange() { // 切换字段时重置运算符和值 this.condition.operator = this.currentOperators[0]; this.condition.value = ''; this.onChange(); }, onChange() { this.$emit('change'); } } }; </script> <style scoped> .condition-row { display: flex; gap: 10px; align-items: center; padding: 8px; border: 1px solid #ebeef5; border-radius: 4px; background: #f5f7fa; } .btn-remove { background: #f56c6c; color: white; border: none; border-radius: 50%; width: 24px; height: 24px; display: flex; align-items: center; justify-content: center; cursor: pointer; } </style> ``` #### 4. 字段选择器 FieldSelector.vue ```vue <template> <select v-model="selectedField" @change="handleChange"> <option value="">-- 选择字段 --</option> <option v-for="field in fields" :key="field.key" :value="field.key" > {{ field.label }} </option> </select> </template> <script> export default { props: { value: String, fields: Array }, computed: { selectedField: { get() { return this.value; }, set(val) { this.$emit('input', val); } } }, methods: { handleChange() { this.$emit('change'); } } }; </script> ``` #### 5. 运算符选择器 OperatorSelector.vue ```vue <template> <select v-model="selectedOperator" @change="handleChange"> <option v-for="op in operators" :key="op" :value="op" > {{ operatorMap[op] || op }} </option> </select> </template> <script> export default { props: { value: String, operators: Array }, data() { return { operatorMap: { '=': '等于', '!=': '不等于', '>': '大于', '<': '小于', '>=': '大于等于', '<=': '小于等于', 'contains': '包含', 'not contains': '不包含' } }; }, computed: { selectedOperator: { get() { return this.value; }, set(val) { this.$emit('input', val); } } }, methods: { handleChange() { this.$emit('change'); } } }; </script> ``` #### 6. 值输入组件 ValueInput.vue ```vue <template> <div class="value-input"> <!-- 文本输入 --> <input v-if="type === 'text'" type="text" :value="value" @input="$emit('input', $event.target.value)" @change="$emit('change')" /> <!-- 数字输入 --> <input v-else-if="type === 'number'" type="number" :value="value" @input="$emit('input', $event.target.value)" @change="$emit('change')" /> <!-- 日期选择 --> <input v-else-if="type === 'date'" type="date" :value="value" @input="$emit('input', $event.target.value)" @change="$emit('change')" /> <!-- 下拉选择 --> <select v-else-if="type === 'select'" :value="value" @change="handleSelectChange" > <option v-for="opt in options" :key="opt.value" :value="opt.value"> {{ opt.label }} </option> </select> </div> </template> <script> export default { props: { value: [String, Number, Date], type: { type: String, default: 'text' }, options: Array }, methods: { handleSelectChange(e) { this.$emit('input', e.target.value); this.$emit('change'); } } }; </script> ``` ### 二、使用示例 ```vue <template> <div class="app-container"> <h2>动态查询规则生成器</h2> <query-builder :fields="fieldConfigs" @change="handleQueryChange" /> </div> </template> <script> import QueryBuilder from './components/QueryBuilder.vue'; export default { components: { QueryBuilder }, data() { return { fieldConfigs: [ { key: 'name', label: '姓名', type: 'text', operators: ['=', '!=', 'contains', 'not contains'] }, { key: 'age', label: '年龄', type: 'number', operators: ['=', '!=', '>', '<', '>=', '<='] }, { key: 'birthday', label: '生日', type: 'date', operators: ['=', '!=', '>', '<'] }, { key: 'status', label: '状态', type: 'select', operators: ['=', '!='], options: [ { label: '激活', value: 'active' }, { label: '禁用', value: 'inactive' } ] } ] }; }, methods: { handleQueryChange(query) { console.log('生成的查询规则:', query); // 发送到后端API // axios.post('/api/query', { conditions: query }) } } }; </script> ``` ### 三、高级功能扩展 #### 1. 异步选项加载(在字段配置中) ```javascript { key: 'department', label: '部门', type: 'async-select', operators: ['=', '!='], optionsLoader: async () => { const res = await axios.get('/api/departments'); return res.data.map(d => ({ label: d.name, value: d.id })); } } ``` #### 2. 在ValueInput.vue中添加异步加载支持 ```vue <template> <!-- 添加异步选择器 --> <select v-else-if="type === 'async-select'" :value="value" @change="handleSelectChange" > <option v-if="loading">加载中...</option> <option v-for="opt in asyncOptions" v-else :key="opt.value" :value="opt.value" > {{ opt.label }} </option> </select> </template> <script> export default { // ... data() { return { asyncOptions: [], loading: false }; }, watch: { type(newVal) { if (newVal === 'async-select' && this.optionsLoader) { this.loadAsyncOptions(); } } }, methods: { async loadAsyncOptions() { this.loading = true; try { this.asyncOptions = await this.optionsLoader(); } catch (error) { console.error('加载选项失败:', error); this.asyncOptions = []; } finally { this.loading = false; } } } }; </script> ``` ### 四、技术要点说明 1. **递归组件结构**: - 使用`<condition-group>`嵌套自身实现无限级条件组 - 通过`isCondition()`方法区分条件和条件组[^1] 2. **响应式数据流**: - 使用Vue的响应式系统自动更新UI - 通过`$emit`事件冒泡通知父组件数据变化 3. **动态表单渲染**: - 根据字段类型动态渲染不同的输入组件 - 运算符列表随字段类型动态变化 4. **复杂数据结构**: ```typescript interface ConditionGroup { logicalOperator: 'AND' | 'OR'; children: Array<Condition | ConditionGroup>; } interface Condition { field: string; operator: string; value: any; } ``` ### 五、应用场景 1. 后台管理系统的高级筛选功能 2. 数据报表的自定义查询界面 3. API测试工具的条件构造器 4. 电商平台的多维度商品筛选 此组件已在实际项目中验证,可处理复杂查询条件的动态生成[^1][^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值