【发布时间】:2018-01-08 07:50:56
【问题描述】:
我想让用户控制基类的“内部类型”。此代码运行良好。
版本 1 (demo)
//library layer
template<class Derived> class BT_trait{
public: using type=int;
};
template<class Derived> class BT{
public: using typee=typename BT_trait<Derived>::type;
public: typee f(){ return 1;}
};
//user code below
class C;
template<> class BT_trait<C>{
public: using type=std::string; //<-- user want to set "internal type"
};
class C : public BT<C> {
public: typee f(){ return "OK";}
};
int main(){
C bt;
std::cout<< bt.f();
}
如果我通过添加模板参数使其更复杂一点,它将不再可编译。
(如下所示)
第 2 版 (demo)
template<class Derived> class BT_trait{
public: using type=int;
};
template<class Derived,class Dummy> class BT{
public: using typee=typename BT_trait<Derived>::type;
public: typee f(){ return 1;}
};
//user code below
template<class T> class C;
template<class T> class BT_trait<C<T>>{
public: using type=std::string;
};
template<class T> class C : public BT<C<T>,T> {
// public: typename BT<C<T>, T>::typee f(){ return "OK";} //Version #2b
public: typee f(){ return "OK";} //Version #2a
//^ error: 'typee' does not name a type; did you mean 'wctype'?
};
int main(){
C<int> bt;
std::cout<< bt.f();
}
但是如果我使用#2b(脏)而不是#2a(简洁),上面的代码就可以正常工作。
为什么?是否可以使#2a 工作?
根据Specialization of template function after point of use will break the compilation 的引用:-
Section [temp.expl.spec] 14.7.3p6 : 如果是模板,则为成员 模板或类模板的成员是显式特化的 那么该专业化应在第一次使用之前声明 那种会导致隐式实例化的专业化 放置在发生这种使用的每个翻译单元中;不 需要诊断。
我怀疑我的代码是未定义的行为。对吗?
我对模板专业化很陌生。
【问题讨论】:
-
对我有用,我不明白你为什么需要在
class BT中使用 Dummy 参数? -
@Yola 你在用VS吗?
-
@Angew 是的.....
-
@Yola VS 没有正确进行两阶段查找,因此即使符合标准的编译器没有,它也会解析代码。
-
这在默认设置的 VS2017 中不起作用 (
/permissive-)。
标签: c++ c++14 language-lawyer template-specialization typetraits