C++ C++;为特定模板专门化添加重载方法
我有一个非常有趣的问题:我有两个模板类。一个可以接受任何模板参数,另一个更专业(对于这个玩具问题,我们会说它必须接受浮点) 问题就在这里:按原样,对C++ C++;为特定模板专门化添加重载方法,c++,templates,overloading,template-specialization,name-hiding,C++,Templates,Overloading,Template Specialization,Name Hiding,我有一个非常有趣的问题:我有两个模板类。一个可以接受任何模板参数,另一个更专业(对于这个玩具问题,我们会说它必须接受浮点) 问题就在这里:按原样,对foo(MustBeFloat&)的调用通过名称隐藏隐藏在子类中,编译器会给我“没有匹配的方法foo调用”错误。如果我使用Parent::foo添加行为了降低成本,我在实例化非浮点foo时出现了“父类中不存在foo”错误,因为该方法不存在那么远 有什么想法吗?如果有更优雅/有效的解决方案,我可以将整个解决方案删除 编辑:只是澄清一下:我在这里进行显式
foo(MustBeFloat&)
的调用通过名称隐藏隐藏在子类中,编译器会给我“没有匹配的方法foo调用”错误。如果我使用Parent::foo添加行
为了降低成本,我在实例化非浮点foo
时出现了“父类中不存在foo”错误,因为该方法不存在那么远
有什么想法吗?如果有更优雅/有效的解决方案,我可以将整个解决方案删除
编辑:只是澄清一下:我在这里进行显式实例化,这就是为什么我只需要在有浮点模板参数的情况下才需要该方法存在的原因
template class Foo<int>;
template class Foo<float>;
模板类Foo;
模板类Foo;
这将实例化每个类成员,因此依赖于不实例化某些方法的方法是不可行的
伊迪丝2:好吧,我想得太多了。以下是我将采用的解决方案:
template<class T>
class Foo
{
public:
template<class T2>
void foo( MustBeFloat<T2> & x ){ static_assert( std::is_same<T,T2>::value, ""); /* ... */}
void foo( CanBeAnything<T> & x ){ /* ... */ }
};
template class Foo<int>;
template class Foo<float>;
template void Foo::foo<float>(MustBeFloat<float> &);
模板
福班
{
公众:
模板
void foo(MustBeFloat&x){static_断言(std::is_same::value,“”;/*…*/}
void foo(CanBeAnything&x){/*…*/}
};
模板类Foo;
模板类Foo;
模板void Foo::Foo(MustBeFloat&);
这一切都很有效。耶!感谢帮助我找到这个解决方案并提出其他更具创造性的解决方案的人。这可能就足够了:
template <class T, bool isFloat, class Other>
struct FooTraits;
template <class T, class Other>
struct FooTraits<T, true, Other> { typedef MustBeFloat<T> MaybeFloat; };
template <class T, class Other>
struct FooTraits<T, false, Other> { typedef Other MaybeFloat; };
template <class T>
class Foo
{
template <class U> friend class FooTraits<U>;
class PrivateType {};
public:
typedef typename FooTraits<T,
std::is_floating_point<T>::value,
PrivateType>::MaybeFloat MaybeFloat;
void foo(CanBeAnything<T>&);
void foo(MaybeFloat&);
};
模板
结构足迹;
模板
struct FooTraits{typedef MustBeFloat MaybeFloat;};
模板
struct FooTraits{typedef Other MaybeFloat;};
模板
福班
{
模板朋友类鞋垫;
类PrivateType{};
公众:
typedef typename FooTraits::MaybeFloat MaybeFloat;
无效的foo(CanBeAnything&);
无效的foo(可能会被忽略&);
};
如果
T
是浮点,则MaybeFloat
将是MustBeFloat
的类型定义。否则,它将是Foo
的私有成员类,因此Foo()
的调用方不可能合成该类型的左值。确定。所以我还没有完全测试过这个,但是如果你有回复,我会评论或者修改这个建议。但下面是一些示例代码,这些代码应该在简化测试用例中的foo()版本中编译,并且特定于父类使用的类型:
template< typename T >
class TestClass
{
typedef struct PlaceholderType {};
public:
template< typename T2 >
typename std::enable_if< !std::is_same<T2, PlaceholderType>::value && std::is_same<T, float>::value, void >::type MyFunc( T2 param ) { std::cout << "Float"; }
template< typename T2 >
typename std::enable_if< !std::is_same<T2, PlaceholderType>::value && !std::is_same<T, float>::value, void >::type MyFunc( T2 param ) { std::cout << "Non-float"; }
};
int main(int argc, char* argv[])
{
TestClass<int> intClass; // should only have the MyFunc(int) version available
TestClass<float> floatClass; // should only have the MyFunc(float) version available
intClass.MyFunc(5); // should output "Non-float"
intClass.MyFunc(5.0f); // should output "Non-float"
floatClass.MyFunc(2.0f); // should output "Float"
floatClass.MyFunc(2); // should output "Float"
}
模板
类TestClass
{
typedef结构占位符类型{};
公众:
模板
typename std::enable_if<!std::is_same::value&&std::is_same::value,void>::type MyFunc(T2参数){std::cout
typename std::enable_if<!std::is_same::value&&!std::is_same::value,void>::type MyFunc(T2参数){std::cout只是为了澄清:当value_type是一个float时,您希望Foo同时具有MustBeFloat和CanBeAnything版本的Foo()?@qeadz这就是目的,是的。如果描述中不清楚,很抱歉。好的。使用“foo”之类的示例总是被简化,所以这个建议可能不起作用。如果您只需要一个专门版本的foo()要在value_type为float时出现,那么不从FooSpecialization派生如何。只需拥有函数foo()的多个版本在类Foo内部。使用enable\u if只根据值类型编译所需的版本。如果更清楚的话,我可以在答案中键入代码片段……老实说,这是我第一次听说使用“enable\u if”.我做了一个模型,这正是我所需要的。如果你想复制粘贴它作为实际答案,我会将其标记为正确。你的问题已经解决,所以我现在不太愿意花时间去过问。如果有人发布了更详细的答案,那么一定要将其标记为正确-高质量的答复需要时间,而且对ge的这个网站是有益的neral(我只是太懒了,不想一直这么做)。这真的很聪明。我将看看enable_if解决方案,但这是一种避免问题的有趣方法。它也很有效,这也很有用。你的魔法很有效。我将选择这个作为正确答案,因为你首先提出了它,但以后阅读此解决方案的人应该看看Oktal建议的其他解决方案这是因为他们也解决了问题。只需一秒钟。我改进了它(比萨饼还在我们的午餐会上,所以我有时间)。我提到的这个版本在技术上仍然不正确。我现在正在用更新的版本替换答案。这是一种与我正在解决的问题不同的解决方案…我真的不希望有一个非浮点版本。但你确实给了我使用的解决方案的想法…只需对函数进行模板化,这样它就不会立即出现已与班上其他同学联系。如有必要,请不要启用。
template <class T, bool isFloat, class Other>
struct FooTraits;
template <class T, class Other>
struct FooTraits<T, true, Other> { typedef MustBeFloat<T> MaybeFloat; };
template <class T, class Other>
struct FooTraits<T, false, Other> { typedef Other MaybeFloat; };
template <class T>
class Foo
{
template <class U> friend class FooTraits<U>;
class PrivateType {};
public:
typedef typename FooTraits<T,
std::is_floating_point<T>::value,
PrivateType>::MaybeFloat MaybeFloat;
void foo(CanBeAnything<T>&);
void foo(MaybeFloat&);
};
template< typename T >
class TestClass
{
typedef struct PlaceholderType {};
public:
template< typename T2 >
typename std::enable_if< !std::is_same<T2, PlaceholderType>::value && std::is_same<T, float>::value, void >::type MyFunc( T2 param ) { std::cout << "Float"; }
template< typename T2 >
typename std::enable_if< !std::is_same<T2, PlaceholderType>::value && !std::is_same<T, float>::value, void >::type MyFunc( T2 param ) { std::cout << "Non-float"; }
};
int main(int argc, char* argv[])
{
TestClass<int> intClass; // should only have the MyFunc(int) version available
TestClass<float> floatClass; // should only have the MyFunc(float) version available
intClass.MyFunc(5); // should output "Non-float"
intClass.MyFunc(5.0f); // should output "Non-float"
floatClass.MyFunc(2.0f); // should output "Float"
floatClass.MyFunc(2); // should output "Float"
}