Clang对已使用的类型别名发出“未使用类型别名”警告咨询
嘿,我来帮你解决这段代码触发的Clang警告问题!首先得说清楚为啥会出警告:
在C03及更早的标准里,函数内部定义的局部类(比如你在get_value<T>()里的value_t)是不允许作为模板参数去实例化其他模板的。哪怕你用的是C11及以后的标准(这时候标准已经允许这种用法了),Clang有时候还是会揪着这点给你发个警告;另外,在局部类里用this_t(也就是自身类型)去实例化value_holder的时候,编译器在分析类型完整性上可能也会有点"纠结",这也是警告的潜在原因。
下面给你几个实用的解决方案,按需选就行:
方案1:把局部类移到函数外面(最推荐)
把value_t从get_value函数内部挪出来,改成模板的嵌套类,这样它就不再是局部类,警告自然就消失了:
template<class T> struct value_holder { T value; }; // 用一个辅助模板来装value_t template<class T> struct get_value_helper { struct value_t { using this_t = value_t; static value_holder<this_t> val() { return value_holder<this_t>(); } operator int() { return 0; } }; }; template<class T> int get_value() { return typename get_value_helper<T>::value_t::val().value; }
方案2:简化写法,去掉this_t直接用value_t
如果你非要保留函数内部类的写法,可以直接在val()里用value_t代替this_t。本质逻辑没变,但有时候能让Clang的警告分析更顺畅:
template<class T> struct value_holder { T value; }; template<class T> int get_value() { struct value_t { static value_holder<value_t> val() { return value_holder<value_t>(); } operator int() { return 0; } }; return value_t::val().value; }
要是还是有警告,也可以用Clang的编译选项-Wno-local-template-args来抑制这个特定警告,但这种"压警告"的方法我不太推荐,能从代码结构上解决就尽量别用。
方案3:用C++14的自动推导返回类型
如果你的编译环境支持C++14及以上,可以把val()的返回类型改成auto,让编译器自动推导,这样就不用显式写value_holder<this_t>,也能绕开类型相关的警告:
template<class T> struct value_holder { T value; }; template<class T> int get_value() { struct value_t { using this_t = value_t; static auto val() { return value_holder<this_t>(); } operator int() { return 0; } }; return value_t::val().value; }
最后提个小细节:你代码里return value_t::val().value;这一行,value_holder<value_t>的value是value_t类型,靠value_t的operator int()转换成int返回,这本身没问题,但如果Clang有隐式转换的警告,你可以加个显式转换:return static_cast<int>(value_t::val().value);,这样更严谨。
内容的提问来源于stack exchange,提问作者Chris Hunt

