我一直在尝试使用模板和表单代码进行类型推断/打印:
#include <iostream>
template <typename T>
class printType {};
template <typename T>
std::ostream& operator<<(std::ostream& os, const printType<T>&)
{
os << "SomeType"; return os;
}
template <typename T>
std::ostream& operator<<(std::ostream& os, const printType<T*>&)
{
os << printType<T>() << "*"; return os;
}
template <typename T>
std::ostream& operator<<(std::ostream& os, const printType<T&>&)
{
os << printType<T>() << "&"; return os;
}
// etc... and can call on a variable through
template <typename T>
printType<T> print(T) { return printType<T>(); }
int main()
{
int a = 7;
int *p = &a;
int &r = a;
//OK: return SomeType*
std::cout << "type of p: " << print(p) << std::endl;
//Hmmmm: returns SomeType <- (no &: can I get around this?)
std::cout << "type of r: " << print(r) << std::endl;
}我想知道是否可以让最后一行返回int&,也就是:
(i)让函数模板print推导出它的参数类型为int&,或者以某种方式计算出当我传递r时它应该返回一个printType<T&>;或者
(Ii)由于变量传递给函数的方式,这是否不可避免。
有没有办法通过改变打印的形式或者使用一些其他的模板技巧来解决这个问题呢?如果有解决方案,我更倾向于非C++0x,但如果将来还没有捷径可用,看看有什么捷径总是很好的。
发布于 2010-09-24 19:52:33
没有办法解决这个问题。在p命名引用的表达式p中,始终具有引用所引用的类型。任何表达式都不会有T&类型。因此,您无法检测表达式是否源自引用。
使用C++0x也无法做到这一点。没有具有引用类型的表达式,这是C++的一个深层原则。您可以编写decltype(r)来获取r名称的类型,而不是表达式r具有的类型。当然,除非print是一个宏,否则你将无法编写print(r),但我不明白你为什么要走这条可怕的路。
发布于 2010-09-24 21:51:40
我收回我之前说过的话。我想我可能有一种方法可以在纯c/c++中工作,尽管方式非常混乱。您需要将一个指针传递到您的函数中...
即bool hello_world(std::string & my_string,const std::string * const my_string_ptr) {
bool hello_world(std::string my_string,const std::string * const my_string_ptr) {
如果您现在测试了
if ( &my_string == my_string_ptr )
如果通过引用传递变量,它将计算为true,如果通过值传递,则计算为false。
当然,在所有函数中将变量加倍可能并不值得……
约翰尼斯是对的。不是在纯c++中。但你能做到的。诀窍就是作弊。使用像perl这样的嵌入式脚本语言来搜索源代码。下面是一个嵌入式perl模块:
http://perldoc.perl.org/perlembed.html
向其传递函数名、变量名和源位置,然后使用正则表达式查找变量并检查其类型。实际上,对于你的代码来说,这可能是一个更好的解决方案,假设你总是手头有一个源代码。
我将在稍后发布此基本方法的函数。我得处理一些早班工作!:)
即使您不想分发源代码,您也可以创建某种打包的函数/var数据文件,您可以通过@ runtime解析该文件并获得等效的结果。
编辑1个
例如..。使用Perl嵌入教程中的# I32 match(SV *string, char *pattern)函数,您可以执行以下操作:
bool is_reference(const char * source_loc, const char * function_name,
const char * variable_name) {
std::ifstream my_reader;
char my_string[256];
SV * perl_line_contents;
bool ret_val = false;
char my_pattern [400]=strcat("m/.*",function_name);
my_pattern=strcat(my_pattern, ".*[,\s\t]*");
my_pattern=strcat(my_pattern, variable_name);
my_pattern=strcat(my_pattern, "[\s\t]*[\(,].*$");
my_reader.open(source_loc.c_str());
while (!my_reader.eof()) {
my_reader.getline(my_string,256);
sv_setpv(perl_line_contents,my_string);
if(match(perl_line_contents,my_pattern)) {
ret_val= true;
}
}
return ret_val;
}..。那里..。有两种方法可以做到这一点(参见上面的更新)。
发布于 2012-12-24 15:03:03
你可以将SFINAE与整型或任何你可以以这种方式从"0“转换的类型一起使用:
template <typename T>
class is_reference
{
struct yes { char a, b; };
typedef char no;
template <typename U> static no test(T y) { }
template <typename U> static yes test(...) { }
public:
static const bool value = sizeof(test<T>(0)) == sizeof(yes);
};
#include <iostream>
struct not_constructable_from_int {};
struct constructable_from_int { constructable_from_int(int x) { } };
int
main()
{
std::cout << is_reference<int>::value << std::endl;
std::cout << is_reference<int&>::value << std::endl;
std::cout << is_reference<not_constructable_from_int>::value << std::endl;
std::cout << is_reference<not_constructable_from_int&>::value << std::endl;
std::cout << is_reference<constructable_from_int>::value << std::endl;
std::cout << is_reference<constructable_from_int&>::value << std::endl;
}注意,测试基本上是“您是否可以调用test<T>(0)”,如果T是一个引用,或者如果T只是任何不能从0转换的类,则不能这样做。不幸的是,你总是可以调用test<T>(T()),这让我有点吃惊(即使T是int)。
正如您所看到的,如果您愿意让您的类型可以从int构造,那么测试就可以在它们上工作,考虑到test<T>(T())结果,这真的让我感到困惑……
https://stackoverflow.com/questions/3786736
复制相似问题