C++ 引用的模板类型推断

C++ 引用的模板类型推断,c++,templates,c++11,C++,Templates,C++11,我一直在使用带有表单代码的模板进行类型推断/打印: #include <iostream> template <typename T> class printType {}; template <typename T> std::ostream& operator<<(std::ostream& os, const printType<T>&) { os << "SomeType"; ret

我一直在使用带有表单代码的模板进行类型推断/打印:

#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;
}
#包括
模板
类printType{};
模板

std::ostream&operator没有办法解决这个问题。表达式
p
,其中
p
命名引用,始终具有引用所引用的类型。没有表达式具有类型
T&
。因此,您无法检测表达式是否源自引用


这也不能用C++0x完成。C++的深层原理是没有引用类型的表达式。您可以编写
decltype(r)
来获取
r
名称的类型,而不是表达式
r
的类型。但是你将无法编写
print(r)
,除非
print
是一个宏,当然,但我不明白你为什么要走那条可怕的路

我收回了我之前说过的话。我想我可能有办法在纯c/c++中实现这一点,尽管方式非常混乱。你会的 需要将指针传递到函数中

i、 e。 bool hello_world(std::string和my_string,const std::string*const my_string\u ptr){

bool hello_world(std::string my_string,const std::string*const my_string_ptr){

如果你现在测试

if(&my\u string==my\u string\u ptr)

如果var通过引用传递,它将计算true,如果通过值传递,它将计算false

当然,在所有函数中将变量加倍可能是不值得的


Johannes是正确的……不是纯C++。但是你可以做到这一点。窍门是作弊。使用像Perl这样的嵌入式脚本语言来搜索你的源代码。这里有一个嵌入式Perl模块:

将函数名、变量名和源位置传递给它,然后使用正则表达式查找变量并检查其类型。实际上,假设您总是手头有一个源代码,这可能是一个更好的解决方案

我将在稍后发布此基本方法的函数…必须处理一些早上的工作!:)

即使您不想分发源代码,您也可以创建某种打包函数/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;
}

…有两种方法可以做到这一点(请参见上面的更新)。

您可以将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;
}
模板
类是您的参考
{
结构yes{char a,b;};
typedef字符号;
模板静态无测试(Ty){}
模板静态是测试(…){}
公众:
静态常量布尔值=sizeof(测试(0))==sizeof(是);
};
#包括
结构不可从{u int}构造;
结构可构造的{u int{可构造的{u int(intx){};
int
main()
{

我能建议他作弊吗…见下文。