请教一个C++template基础语法问题

WingForce 2009-02-18 04:35:30

template<char* str>
struct some_template
{
static const char* get_value() { return str; };
};

void foo()
{
cout << some_template<"abcd">::get_value() << endl;
}



这个东东明显是不能通过编译的,有没有类似的东西,可以把字符串和编译期类型关联,因为毕竟字符串也是文字常量,编译期已经知道其值了。。

...全文
480 42 打赏 收藏 转发到动态 举报
写回复
用AI写文章
42 条回复
切换为时间正序
请发表友善的回复…
发表回复
xuhb95083023 2009-02-25
  • 打赏
  • 举报
回复
[Quote=引用 41 楼 xuhb95083023 的回复:]
有三个办法,第一个办法15楼已经说明过了,用的是外部链接对象,因为模板实参只能是外部链接对象或者整型或者普通类,所以还可以通过整形或者普通类来解决这个问题,当然用整形不大直观,所以一般用枚举代替
方法一:参考15楼

方法二:用枚举或者整形

C/C++ code
typename enum {
apple,
orange
} fruit;

template <typename fruit f>
struct get_fruit_string;

template <>
struct get_fruit_str…
[/Quote]

基于模板实参的类型限制,应该没有第四种方法了
xuhb95083023 2009-02-25
  • 打赏
  • 举报
回复
有三个办法,第一个办法15楼已经说明过了,用的是外部链接对象,因为模板实参只能是外部链接对象或者整型或者普通类,所以还可以通过整形或者普通类来解决这个问题,当然用整形不大直观,所以一般用枚举代替
方法一:参考15楼

方法二:用枚举或者整形

typename enum {
apple,
orange
} fruit;

template <typename fruit f>
struct get_fruit_string;

template <>
struct get_fruit_string<orange> {
static string get_string() {
return "orange";
}
}

template <>
struct get_fruit_string<apple> {
static string get_string() {
return "apple";
}
}

// 调用方法:
cout << get_fruit_string<apple>::get_string() << endl;



方法三:用标签类,这个技巧在 boost库中经常可以看到

struct apple{}
struct orange{}

template <typename T>
struct get_fruit_string;

template <>
struct get_fruit_string<apple> {
static string get_string() {
return "apple";
}
}

template <>
struct get_fruit_string<orange> {
static string get_string() {
return "orange";
}
}

// 调用方法:
cout << get_fruit_string<apple>::get_string() << endl;

yshuise 2009-02-24
  • 打赏
  • 举报
回复
[Quote=引用 34 楼 taodm 的回复:]
编译期构造,可以认为是元编程。
lex/yacc其实远比spirit库可读。
所以,你真的需要编译期行为么?
[/Quote]
lex 不是开源的,你读过吗?
fairchild811 2009-02-24
  • 打赏
  • 举报
回复
hai040 2009-02-24
  • 打赏
  • 举报
回复
m
逸萌 2009-02-24
  • 打赏
  • 举报
回复
UP
nicknide 2009-02-22
  • 打赏
  • 举报
回复
[Quote=引用 33 楼 WingForce 的回复:]
其实原理我是知道的,只是想寻求一个workaround的解决方案而已,多谢各位。
事实上,目前看来不能直接特化的话,其他解决方法对我来说意义不是非常大,因为需要的是语法上的清晰。

根本的目的比较无聊,是想在编译期构造SQL串,甚至想到了做整套的编译期字符串运算,但是即使那样,使用起来也难以和自然的字符串相比,可读性太差了。
[/Quote]

纯编译期实现模板拼接字符串而完全避免运行时拼接开销, 似乎没有这个可能 -_-
nineforever 2009-02-19
  • 打赏
  • 举报
回复
[Quote=引用 33 楼 WingForce 的回复:]
其实原理我是知道的,只是想寻求一个workaround的解决方案而已,多谢各位。
事实上,目前看来不能直接特化的话,其他解决方法对我来说意义不是非常大,因为需要的是语法上的清晰。

根本的目的比较无聊,是想在编译期构造SQL串,甚至想到了做整套的编译期字符串运算,但是即使那样,使用起来也难以和自然的字符串相比,可读性太差了。
[/Quote]

pre-build的时候做就可以了。不必每次编译都重新解析一次
taodm 2009-02-19
  • 打赏
  • 举报
回复
编译期构造,可以认为是元编程。
lex/yacc其实远比spirit库可读。
所以,你真的需要编译期行为么?
WingForce 2009-02-19
  • 打赏
  • 举报
回复
其实原理我是知道的,只是想寻求一个workaround的解决方案而已,多谢各位。
事实上,目前看来不能直接特化的话,其他解决方法对我来说意义不是非常大,因为需要的是语法上的清晰。

根本的目的比较无聊,是想在编译期构造SQL串,甚至想到了做整套的编译期字符串运算,但是即使那样,使用起来也难以和自然的字符串相比,可读性太差了。
redleaves 2009-02-19
  • 打赏
  • 举报
回复
[Quote=引用 26 楼 nineforever 的回复:]
mangling并不是主要问题。特殊字符可以escape,太长会截断(类似于VC6中的map)
关键在于string literal不满足non-type argument的要求

1 A template-argument for a non-type, non-template template-parameter shall be one of:
— an integral constant expression; or
— the name of a non-type template-parameter; or
— the address of an object or function with external linkage, including function templates and function
template-ids but excluding non-static class members, expressed as & id-expression where the & is
optional if the name refers to a function or array, or if the corresponding template-parameter is a
reference; or
— a constant expression that evaluates to a null pointer value (4.10); or
— a constant expression that evaluates to a null member pointer value (4.11); or
— a pointer to member expressed as described in 5.3.1.
2 [ Note: A string literal does not satisfy the requirements of any of these categories and thus is not
an acceptable template-argument. [ Example:
template <class T, char* p> class X {
X();
X(const char* q) { /* ... */ }
};
X <int, "Studebaker"> x1; // error: string literal as template-argument
char p[] = "Vivisectionist";
[/Quote]
正解.
Name Mangling不是关键,甚至不是问题.完全可以做出能解释字符串的机制.
这个问题主要是由于template的非类型参数在设计的时候被当做一个数值来使用造成的.所以,无法变成确定数值的参数不能做为非类型参数.原则上,无论是string还是float都是应该可以做为非类型参数的.
chenzhp 2009-02-19
  • 打赏
  • 举报
回复
最安全,最舒心的就是直接特化。楼主真有想法!
lllsui 2009-02-19
  • 打赏
  • 举报
回复
学习
weimin19861015 2009-02-18
  • 打赏
  • 举报
回复
怎么是结构体啊,用类不更好吗
KHacker_001 2009-02-18
  • 打赏
  • 举报
回复
学习
逸萌 2009-02-18
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 maenxiang 的回复:]
这个和指针类型的模板参数的Name Mangling机制有关。指针类型的模板参数Name Mangling之后,指针作为函数名显然不稳定。因此需要一个确切的有名字的extern对象的地址。如有一个全局字符串变量。比如15楼的例子,就对了。但是如果改为char * p1="aaa"; 则也不行,需要对象的地址。
看看G++ Name Mangle之后的样子 __ZN13some_templateIXadL_Z2p1EEE9get_valueEv 就明白了。

而对于int类型,则可以直接使用数据作为Name Mang…
[/Quote]
学习!顶
nineforever 2009-02-18
  • 打赏
  • 举报
回复
[Quote=引用 23 楼 maenxiang 的回复:]
引用 21 楼 nineforever 的回复:
mangling并不是主要问题。特殊字符可以escape,太长会截断(类似于VC6中的map)
关键在于string literal不满足non-type argument的要求


这个是规范。我说的为什么要这样。我说的是原因,这位大侠说的是结果啊。
[/Quote]

原因那段标准里说了,是因为string literal没有external linkage。这样它的地址就不是唯一的

Whether all string literals are distinct (that is, are stored in nonoverlapping objects) is implementationdefined.

类似的,static对象的地址也不能作为模板参数

template<int *> void f();

static int a;
extern int b;

int main()
{
f<&a>(); //fail
f<&b>(); //OK
}
waizqfor 2009-02-18
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 nineforever 的回复:]
引用 17 楼 maenxiang 的回复:
这个和指针类型的模板参数的Name Mangling机制有关。指针类型的模板参数Name Mangling之后,指针作为函数名显然不稳定。因此需要一个确切的有名字的extern对象的地址。如有一个全局字符串变量。比如15楼的例子,就对了。但是如果改为char * p1="aaa"; 则也不行,需要对象的地址。
看看G++ Name Mangle之后的样子 __ZN13some_templateIXadL_Z2p1EEE9get_valueEv 就明白了。

而对于int类型,则…
[/Quote]
学习!~
darkread 2009-02-18
  • 打赏
  • 举报
回复
c++ Primer有这样的例子,必须是标准c++编译器才能编译通过,我前两天刚刚看过
maenxiang 2009-02-18
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 nineforever 的回复:]
mangling并不是主要问题。特殊字符可以escape,太长会截断(类似于VC6中的map)
关键在于string literal不满足non-type argument的要求
[/Quote]

这个是规范。我说的为什么要这样。我说的是原因,这位大侠说的是结果啊。
加载更多回复(22)

65,211

社区成员

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

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