2012-06-06 60 views
3

std::reference_wrapper使用指针下方的指针来存储“引用”,我试图做类似于下面的代码。std :: enable_if与std :: is_reference无法编译

#include <type_traits> 

struct Foo 
{ 
    void* _ptr; 

    template<typename T> 
    Foo(T val, 
     typename std::enable_if 
      < 
       std::is_reference<T>::value, 
       void 
      >::type* = nullptr) 
     : _ptr(&val) 
    { } 
}; 

int main() 
{ 
    int i = 0; 
    int& l = i; 

    Foo u2(l); 

    return 0; 
} 

然而,这无法编译:

CXX main.cpp 
main.cpp: In function ‘int main()’: 
main.cpp:23:13: error: no matching function for call to ‘Foo::Foo(int&)’ 
main.cpp:23:13: note: candidates are: 
main.cpp:8:5: note: template<class T> Foo::Foo(T, typename std::enable_if<std::is_reference<_Tp>::value, void>::type*) 
main.cpp:8:5: note: template argument deduction/substitution failed: 
main.cpp: In substitution of ‘template<class T> Foo::Foo(T, typename std::enable_if<std::is_reference<_Tp>::value, void>::type*) [with T = int]’: 
main.cpp:23:13: required from here 
main.cpp:8:5: error: no type named ‘type’ in ‘struct std::enable_if<false, void>’ 
main.cpp:3:8: note: constexpr Foo::Foo(const Foo&) 
main.cpp:3:8: note: no known conversion for argument 1 from ‘int’ to ‘const Foo&’ 
main.cpp:3:8: note: constexpr Foo::Foo(Foo&&) 
main.cpp:3:8: note: no known conversion for argument 1 from ‘int’ to ‘Foo&&’ 

我怎样才能为参考参数enable_if回是真的吗?

+0

显而易见的答案是在_is_reference &&!is_integral_上进行条件化,并且与之相反,它的工作原理但不是一个好的答案... –

+0

@ K-ballo我已简化了我的问题,并将编辑问题以更加准确反射问题 - 这是如何让'enable_if 对引用有效 –

回答

5

T在这种情况下永远不会被推断为引用类型。在构建对象u2时,构造函数模板参数推导为int

虽然可变u2的类型是int&,当你在表达式中使用u2,它是int类型的左值表达式。 An expression never has reference type.

模板参数推导使用函数参数的类型来推导模板参数类型。函数参数是表达式。因此,由于没有表达式具有引用类型,所以模板参数永远不会被推断为引用类型。

[在C++ 11中,如果函数参数的类型为T&&,T可能推导为类型T&如果参数是一个左值。这种机制可以完美转发。不过,这与您的场景无关。]

实际上,在表达式中,对象和对该对象的引用是无法区分的。引用只允许您为对象提供其他名称。

+0

James,这是一个更复杂的代码片段的一部分,我试图用'enable_if'来区分整数,指针和l值参考。因此,我试图做甚至可能使用'enable_if'? –

+0

不,因为[表达式从来没有引用类型](http://stackoverflow.com/a/10238252/151292)。为什么你认为你需要区分“对象的引用”和“对象”? –

+0

我想使用联合来存储不同的数据类型 - 如果它是整数类型的,我将值本身存储在'union :: uint64_t'成员中,如果它是一个指针,我将值本身存储在联合:: void *'成员,如果它是一个引用,则在'union :: void *'成员中存储引用的**地址**。我想重载联合构造函数来使用模板参数推导来知道如何处理输入参数 –

相关问题