考慮以下基本類模板:
#include <type_traits>
template < typename T >
class A {
public:
A() = default;
T obj;
template < typename U = T, typename = typename std::enable_if< !std::is_void< U >::value >::type >
T& get();
};
我正在使用<type_traits>一個簡單的 SFINAE 實作來隱藏get()模板引數是否為空。
但是,我仍然收到 void types 的編譯器錯誤error: forming reference to void,我不確定原因是。類宣告語法有什么問題嗎?
int main(int argc, char const *argv[]) {
A<int> b;
A<void> t; // error: forming reference to void
return 0;
}
編輯:有人指出問題是obj不能為空。一種解決方法是改用指標:
#include <type_traits>
#include <memory>
template < typename T >
class A {
public:
A() = default;
std::shared_ptr< T > obj;
template < typename U = T, typename = typename std::enable_if< !std::is_void< U >::value >::type >
U& get() { return *obj; };
};
但我仍然得到 error: forming reference to void,這意味著編譯器仍在嘗試編譯get().
uj5u.com熱心網友回復:
第一個問題是您正在嘗試使用
T obj;
其中 T 是void。但根據檔案
以下任何背景關系都需要型別 T 是完整的:
T 型別物件的定義;
但是,由于void是不完整的型別,你的錯誤:
錯誤:'A::obj' 的型別不完整
其次,我們也不能有一個回傳型別,void&這就是為什么你會得到你提到的錯誤:
錯誤:形成對 void 的參考
您可以通過以下方式解決:
#include <type_traits>
#include <iostream>
template < typename T >
class A {
public:
A() = default;
T *obj = nullptr;//note a pointer
template < typename U = T>
typename std::enable_if<!std::is_same<U, void>::value,U&>::type get()
{
std::cout <<"called"<<std::endl;
if(obj != nullptr)
{
std::cout<<"not null"<<std::endl;
return *obj;
}
else
{
std::cout<<"null"<<std::endl;
obj = new T{};
return *obj;
}
}
~A()
{
std::cout<<"destructor called"<<std::endl;
delete obj;
obj = nullptr;
}
};
int main(int argc, char const *argv[]) {
A<int> b;
std::cout<< b.get() <<std::endl;//this will print the string "called" and the integer 0 on console
std::cout<<"------------------"<<std::endl;
int &p = b.get();
std::cout<<"------------------"<<std::endl;
p = 32;
std::cout << b.get()<<std::endl;
std::cout<<"------------------"<<std::endl;
A<void> t;
return 0;
}
另外,不要忘記delete在解構式中使用。
uj5u.com熱心網友回復:
解決此問題的一種簡單方法(甚至符合 C 98)是撰寫A. 這是一個很大的類,但它可能很煩人。
另一種方法是強制obj成為void.
#include <type_traits>
template < typename T >
class A {
public:
A() = default;
struct empty{};
[[no_unique_address]]
std::conditional_t<std::is_same_v<T, void>, empty, T> obj;
template <typename U = T, typename = typename std::enable_if<!std::is_void_v<U>>::type>
U& get() { return obj; }
};
int main()
{
A<void> v;
A<int> x;
int& y = x.get();
}
現場演示。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/362271.html
