我需要一个C ++模板,给定一个类型和该类型的对象,它可以根据类型是否为整数做出决定,同时能够访问实际对象。我试过这个
template <typename T, T &N>
struct C {
enum { Value = 0 };
};
template <int &N>
struct C<int, N> {
enum { Value = N };
};
但它不起作用。有什么方法可以实现类似的东西吗?
修改
我试图实现的是这样的,这将在编译时发生:
if (type is int) {
return IntWrapper<int_value>
else {
return type
}
您实际上可以在模板实例化中传递指向对象或引用,如下所示:
struct X {
static const int Value = 5;
};
template <X *x>
struct C {
static const int Value = (*x).Value;
};
X x;
std::cout << C<&x>::Value << std::endl; // prints 5
但显然所有这一切都是通过推断x
的类型来初始化模板,而x
也需要全局声明。对我正在尝试做的事情毫无用处,我认为这在编译时是不可能的。
答案 0 :(得分:7)
您尝试做的是无效的C ++模板。您不能将任意对象用作模板参数,您可以使用的只是类型,整数文字以及某些特殊情况下的字符串文字。
答案 1 :(得分:5)
除非我误解你,否则你想要的是不可能的。在您的示例中,您显示无效使用指针模板参数。
template <X *x>
struct C {
static const int Value = (*x).Value;
};
这是无效的,因为(*x).Value
必须是一个常量表达式才能初始化Value
。当用作Value
时,确定X
类X::Value
可以作为常量表达式使用。但这一次,它不是因为它涉及一个指针(引用在常量表达式中同样无效)。
总而言之,你不能这样做:
Magic<T, someT>::type
如果T不是int,则期望::type
为T,否则IntWrapper<someT>
为T
,因为{{1}}只能是枚举,整数,指针或引用类型。在后两种情况下,您将无法获得指针所指向的任何内容的“值”或编译时引用所引用的内容。 如果你对此感到满意,很容易解决你的问题,我不会告诉你如何(我怀疑你已经知道如何)。
我认为你已经把自己逼到一种情况,在这种情况下,解决你的问题已经无法按照给定的规则来做。当事情仍然允许解决问题时,请回过头来向我们展示您正试图解决的真正的问题。
答案 2 :(得分:4)
也许一个简单的重载模板方法适用于您的情况?
template<typename T>
void doSomething(const T& x)
{
// ...
}
void doSomething(int x)
{
// ...
}
答案 3 :(得分:3)
template <typename T> struct A
{
enum { Value = false };
};
template <> struct A<int>
{
enum { Value = true };
};
那么:
template <typename T> struct A
{
T value_;
A() : value() {}
enum { is_int = false };
};
template <> struct A<int>
{
int value_;
explicit A( int v ) : value_( v ) {}
enum { is_int = true };
};
答案 4 :(得分:3)
除了其他帖子:您无需再使用enum {}
- 黑客攻击:
template<typename T, int val>
struct Test {
static const int Value = 0;
};
template <int val>
struct Test<int, val> {
static const int Value = val;
};
int main(int argc,char *argv[]) {
const int v = Test<int,1>::Value;
}
答案 5 :(得分:2)
你可以这样做:
template<typename T, int val>
struct Test
{
enum {Value = 0};
};
template <int val>
struct Test<int, val>
{
enum {Value = val};
};
int main(int argc,char *argv[])
{
int v = Test<int,1>::Value;
}
答案 6 :(得分:2)
我需要一个C ++模板,给出一个 它的类型和对象 可以根据是否做出决定 类型是否为整数,而 能够访问实际的 对象。
您可以根据类型是否为整数做出决策,问题是无法使用任何类型的对象声明模板。所以关于如何决定一个类型是一个整数的问题是没有意义的。
请注意,在所有答案中,您的原始模板已整齐地更改为
template < typename T, int >
class C {};
代替你的
template< typename T, T >
class C {};
但是虽然C<int, 5>
是一个完全有效的声明,但对于任意类型T都不是这种情况,点C<float, 5.>
中的情况会给编译器错误。
你能发布你想要达到的目标吗?
并且对于记录,如果第二个模板参数始终是int
,并且您只想在类型为整数类型时获取其值,并且其他为0,则可以执行以下操作:
#include <limits>
template< typename T, int N >
class C {
static const int Value = (std::numeric_limits<T>::is_integer) ? N : 0;
};
答案 7 :(得分:0)
简单修复代码 - 松开引用:
template <typename T, T N>
struct C {
enum { Value = 0 };
};
template <int N>
struct C<int, N> {
enum { Value = N };
};
在模板参数中使用引用无论如何都没有意义,因为你实际上并没有将参数传递到任何地方。
答案 8 :(得分:0)
查看Alexandrescu的Modern C++ Design。我相信第2章有一个正确的例子,说明你想做什么。
答案 9 :(得分:0)
Template specialization可以像这样实现(代码取自www.cplusplus.com):
// template specialization
#include <iostream>
using namespace std;
// class template:
template <class T>
class mycontainer {
T element;
public:
mycontainer (T arg) {element=arg;}
T increase () {return ++element;}
};
// class template specialization:
template <>
class mycontainer <char> {
char element;
public:
mycontainer (char arg) {element=arg;}
char uppercase ()
{
if ((element>='a')&&(element<='z'))
element+='A'-'a';
return element;
}
};
int main () {
mycontainer<int> myint (7);
mycontainer<char> mychar ('j');
cout << myint.increase() << endl;
cout << mychar.uppercase() << endl;
return 0;
}
在您的情况下,您必须在类模板专门化中根据需要替换char。现在,我不确定你想要完成什么,但我希望上面的例子能够很好地指导你如何进行模板专业化。
答案 10 :(得分:0)
我试图实现的是这样的,这将在编译时发生:
if (type is int) {
return IntWrapper<int_value>
else {
return type
}
我不确定你为什么不开始使用IntWrapper。需要将编译时整数常量包装到IntWrapper中,如果它是int?
否则,您会尝试使用仅在运行时可用的数据来实例化模板。