我在C ++中有一个模板类(有点简化):
template<typename T>
struct C
{
T member;
void set(const &T x) { member = x; }
void set(int x) { member = x; }
};
正如您所看到的,set()函数可以被称为 ,类型为T,或者带有int。这工作正常,除非T是一个int,在这种情况下我得到一个模糊的转换错误。我明白为什么会这样,但有没有办法实现我想要的?
答案 0 :(得分:2)
为int提供专业化:
template<>
struct C<int>
{
int member;
void set(int x) { member = x };
};
答案 1 :(得分:1)
解决此问题的一种方法是为int
提供仅具有一个set函数的模板的特化。否则,您可能希望查看Boost库,如果模板元编程代码中的enable_if
之类的内容允许您仅在T不是int类型时打开函数set(int x)
。
答案 2 :(得分:0)
你可以将调用转换为调用代码中的int或const int吗?
答案 3 :(得分:0)
这取决于你真正想做的事情。当您尝试从member
设置T
x
时,您编写的示例没有多大意义,这是int
。虽然有些情况可能有意义,但我怀疑你的真实代码中还有其他东西。
方法必须具有相同的名称吗?如果是这样的话? 专门针对int的struct有意义吗? 你有什么其他限制?
也许这对你有用:
template<typename T>
struct C
{
T member;
template<typename U>
void set(const U& x) { member = x; }
void set(int x) { member = x; }
};
现在set(int)
重载set(const U&)
。 set(const U&)
接受非T
参数,但在尝试分配给X
时可能会失败。它可能允许比set( const T&)
更多的转化。
如果这还不够好,添加extra level of indirection应该可以解决问题:
template<typename T>
struct C
{
T member;
void set(const T& x) { setInternal( x ); }
private:
template<typename U>
void setInternal(const U& x) { member = x; }
void setInternal(int x) { member = x; }
};
答案 4 :(得分:0)
您似乎只有在参数为 T 或 int 时才能使set方法可用。但是,如果您只为 int 专门化C,则所有隐式转换仍然会发生,就像您没有尝试以特殊方式处理 int 类型一样。
如果你真的想要禁用隐式转换,一种方法是使用boost::enable_if
- 只有满足条件才能使方法可用。
#include <boost/type_traits/is_same.hpp>
#include <boost/utility/enable_if.hpp>
template<typename T>
struct C
{
T member;
template <class U>
typename boost::enable_if_c<
boost::is_same<T, U>::value || boost::is_same<U, int>::value
>::type
set(const U& x) { member = x; }
};
int main()
{
C<int> i;
i.set(3.14); //error
i.set(10); //OK
i.set('a'); //error
C<double> d;
d.set(3.14); //OK
d.set(3.14f); //error
d.set(10); //OK
d.set('a'); //error
}
要在没有boost::enable_if
(或自己实现)的情况下获得相同的结果,您可能还需要设置私有的所有不需要的版本(C ++ 0x也允许删除这些过载)。
template<typename T>
struct C
{
T member;
void set(const T& x) { member = x; }
void set(int x) { member = x; }
private:
template <class U>
void set(const U&);
};
template <>
struct C<int>
{
int member;
void set(int x) { member = x; }
private:
template <class U>
void set(const U&);
};
int main()
{
C<int> i;
i.set(3.14); //error
i.set(10); //OK
i.set('a'); //error
C<double> d;
d.set(3.14); //OK
d.set(3.14f); //error
d.set(10); //OK
d.set('a'); //error
}
但是,为 int 设置此异常对我来说似乎相当随意。来自int的转换可能也不是特别安全,例如int->float
可能会丢失大值的精确度,int->short
/ int->char
/ int->unsigned
可能会溢出。