在C++中如何限制模板泛型的类型

zhfkt 2013-04-18 03:33:41
比如说

template<class T>
class Compare
{
public:
static bool IsEqual(const T& lh, const T& rh)
{
return lh == rh;
}
};


如果我只希望仅对float和double有效,但是对其它类型都无效,应该采用什么方法?
...全文
1971 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
mujiok2003 2013-04-19
  • 打赏
  • 举报
回复
bad sleep again:-(

class Compare
{
public:
    template<typename T>
    bool static IsEqual(T const& a, T const& b)
    {
      return a == b;
    }

    static bool IsEqual(double a , double b)
    {
        return a >= b && b <= a;
    }

     static bool IsEqual(float a, float b)
    {
        return a >= b && b <= a;
    }
};

  bool b ;
  b = Compare::IsEqual(1, 2); //generic veriosn
  b = Compare::IsEqual('a', 'b'); //generic veriosn
  b = Compare::IsEqual(1.0f, 2.0f); //float veriosn
  b = Compare::IsEqual(1.0, 2.0); //double  veriosn
ForestDB 2013-04-18
  • 打赏
  • 举报
回复
真的长见识了。
taodm 2013-04-18
  • 打赏
  • 举报
回复
都没看过《modern c++ design》吧 用typelist是最优雅的。boost库里也有类似的关于类型的容器的,优雅性上略不如loki的typelist。
youyou1912 2013-04-18
  • 打赏
  • 举报
回复
第二种方法也推荐. 比较简单.
youyou1912 2013-04-18
  • 打赏
  • 举报
回复
5中方法串烧, 推荐第一种和最后一种
	struct Compare
	{
	  template<class T>
	  static bool IsEqual(const T& t1, const typename std::enable_if<std::is_floating_point<T>::value, T>::type & t2)
	  {
		cout << "t1=" << t1 << "\tt2=" << t2 << endl;
		return t1 == t2;
	  }

	  template<class T>
		static bool IsEqual2(const T& t1, const T& t2)
		{
			static_assert(is_floating_point<T>::value, "floating type unsupported.");
			cout << "t1=" << t1 << "\tt2=" << t2 << endl;
			return t1 == t2;
		}	

		template <class T>
		static bool IsEqual3(const T&t1, const T& t2);

	private:
		template <class T>
		static bool isEqual_Impl(const T& t1, const T& t2)
		{
			return t1 == t2;
		}
	};
	template <>
	static bool Compare::IsEqual3<float>(const float&t1, const float& t2)
	{
		return isEqual_Impl<float>(t1, t2);
	}
	template <>
	static bool Compare::IsEqual3<double>(const double&t1, const double& t2)
	{
		return isEqual_Impl<double>(t1, t2);
	}
	template <>
	static bool Compare::IsEqual3<long double>(const long double&t1, const long double& t2)
	{
		return isEqual_Impl<long double>(t1, t2);
	}

	template <typename T> struct tag;
	template<> struct tag<float>{};
	template<> struct tag<double>{};
	template<> struct tag<long double>{};
	template <typename T>
	struct Compare4 : tag<T>
	{
		static bool IsEqual( const T& t1, const T& t2)
		{
			return t1 == t2;
		}
	};

	// 多一个参数
	template <typename T, typename Enable = void>
	struct Compare5; // not implemented

	template<class T>
	struct Compare5<T, typename enable_if<is_floating_point<T>::value >::type> {
		static bool IsEqual(const T& t1, const T& t2)
		{
			return t1 == t2;
		}
	};

	void test()
	{
		const float& x = 1;
		float y = 2;

		Compare::IsEqual(1.0, 1.0); 
		//Compare::IsEqual(1, 1); // complie error
		Compare::IsEqual(1.0, 1); // allowed
		Compare::IsEqual(x, y);


		Compare::IsEqual2(1.0, 1.0);
		//Compare::IsEqual2(1, 1); // compile error
		//Compare::IsEqual2(1.0, 1);  // not allowed
		Compare::IsEqual2(x, y);

		Compare::IsEqual3(1.0, 1.0); 
		//Compare::IsEqual3(1, 1); // complie error
		//Compare::IsEqual3(1.0, 1); // not allowed
		Compare::IsEqual3(x, y);

		Compare4<float>::IsEqual(1.0, 1.0); 
		//Compare4<int>::IsEqual(1, 1); // complie error
		Compare4<float>::IsEqual(1.0, 1); // allowed
		Compare4<float>::IsEqual(x, y);

		Compare5<float>::IsEqual(1.0, 1.0); 
		//Compare5<int>::IsEqual(1, 1); // complie error
		Compare5<float>::IsEqual(1.0, 1); // allowed
		Compare5<float>::IsEqual(x, y);
	}
fallening 2013-04-18
  • 打赏
  • 举报
回复
引用 楼主 zhfkt 的回复:
比如说 C/C++ code?123456789template<class T>class Compare{public: static bool IsEqual(const T& lh, const T& rh) { return lh == rh; }}; 如果我只希望仅对float和double有效,但是……

template <typename T> struct tag;
template struct tag<float>{};
template struct tag<double>{};

template <typename T>
struct compare : tag<T>
{
    static bool is_equal( const T lhs, const T rhs );
};
rocktyt 2013-04-18
  • 打赏
  • 举报
回复
如果有Concept,很容易就能做到 否则还是先用6楼或者7楼的方法吧 上面有些人只知道is_same却不知道is_floating_point,让我很是惊讶
billzheng 2013-04-18
  • 打赏
  • 举报
回复
You need something like this:
struct Compare
{
  template<class T>
  static bool IsEqual(T t, typename std::enable_if<std::is_floating_point<T>::value, T>::type)
  {
    return true;
  }
};
Compare::IsEqual(3, 2);     // compile error
Compare::IsEqual(3.0, 2.0); // compile ok
FancyMouse 2013-04-18
  • 打赏
  • 举报
回复
为什么不是header里只写声明不写实现,然后cpp里特化?

template class Compare<float>;
template class Compare<double>;
aj3423 2013-04-18
  • 打赏
  • 举报
回复
c++0x 的话
#include <iostream>
using namespace std;

template<class T>
struct Compare {
	static_assert((is_same<T, float>::value)
				|| (is_same<T, double>::value)
				, "not float or double");
};

int main() {
	Compare<float> c;
	Compare<int> c;

	cout << sizeof(c) << endl;

}
Star-light 2013-04-18
  • 打赏
  • 举报
回复
boost::enable_if 配合 type traits 用的技巧是SFINAE
www_adintr_com 2013-04-18
  • 打赏
  • 举报
回复
C++ 没有泛型约束哦, 不知道最新的 C++ 11 有没有. 如果你愿意引入 boost 库的话, 可以这样:

#include <boost/mpl/assert.hpp>
#include <boost/type_traits/is_same.hpp>

template<class T>
class Compare
{
public:
	static bool IsEqual(const T& lh, const T& rh)
	{
		BOOST_MPL_ASSERT_MSG((boost::is_same<T, double>::value || boost::is_same<T, int>::value), type_must_be_int_or_double, (T));
		return lh == rh;
	}
};
不过, boost 实现这些也是依赖于特化的. 当然也可以自己封装类似的东西而不引入 boost
zhfkt 2013-04-18
  • 打赏
  • 举报
回复
引用 1 楼 adlay 的回复:
template<class T> class Compare{}; template <> class Compare<int> { ... }; template <> class Compare<double> { ... };
泛型特化是否在 double模板 和float模板中 对要同一段代码写2遍? c++中的 泛型特化 概念是否对应于 c# 中的 泛型约束?如果不是c++中是否有对应于 c#泛型约束 的方法
www_adintr_com 2013-04-18
  • 打赏
  • 举报
回复
template<class T> class Compare{}; template <> class Compare<int> { ... }; template <> class Compare<double> { ... };

64,646

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧