Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/160.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ SFINAE以启用非模板成员函数_C++_Templates_Sfinae - Fatal编程技术网

C++ SFINAE以启用非模板成员函数

C++ SFINAE以启用非模板成员函数,c++,templates,sfinae,C++,Templates,Sfinae,这可能是重复的,但我只是找不到OP明显存在与我相同问题的地方。 我有一个类,仅当类模板参数不是无符号类型时,我才尝试启用操作符- #include <type_traits> template<class T> struct A { typename std::enable_if<!std::is_unsigned<T>::value,A>::type operator-() {return {};} }; int main() {

这可能是重复的,但我只是找不到OP明显存在与我相同问题的地方。
我有一个类,仅当类模板参数不是无符号类型时,我才尝试启用
操作符-

#include <type_traits>

template<class T>
struct A {
    typename std::enable_if<!std::is_unsigned<T>::value,A>::type operator-() {return {};}
};

int main() {
    A<unsigned> a=a;
}
#包括
模板
结构A{
typename std::enable_if::value,A>::类型运算符-(){return{};}
};
int main(){
A=A;
}
不幸的是,每当我用未签名类型实例化它时,就会产生一个编译器错误,如图所示

main.cpp:5:29: error: no type named 'type' in 'std::enable_if<false, A<unsigned int> >'; 'enable_if' cannot be used to disable this declaration
    typename std::enable_if<!std::is_unsigned<T>::value,A>::type operator-() {return {};}
                            ^~~~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:9:17: note: in instantiation of template class 'A<unsigned int>' requested here
    A<unsigned> a=a;
                ^
main.cpp:5:29:错误:在'std::enable_if';'中没有名为'type'的类型enable_if'不能用于禁用此声明
typename std::enable_if::value,A>::类型运算符-(){return{};}
^~~~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:9:17:注意:在这里请求的模板类“A”的实例化中
A=A;
^

好吧,我可以清楚地看到,如果在这里不起作用,
enable\u。我提到过一个模糊不清的类似问题,我可以使用继承和模板专门化来解决这个问题,但是。。。真的没有更好的方法吗?

一种可能的方法是引入虚拟模板参数:

template<class T>
struct A {
    template<
       typename D = int,
       typename = typename std::enable_if<!std::is_unsigned<T>::value, D>::type
    >
    A operator-() {return {};}
};
模板
结构A{
模板<
typename D=int,
typename=typename std::enable_if::value,D>::type
>
运算符-(){return{};}
};

我曾经遇到过同样的问题。因为默认模板参数不依赖于函数模板中的模板参数,所以不可能出现替换失败。必须将模板参数默认为封闭模板类型,如下所示:

模板::类型>
运算符-(){return{};}

注释有点长:您也可以使用自由函数,即使是一元运算符

#include <type_traits>

template<class T>
struct A {
};

template<class T>
typename std::enable_if<!std::is_unsigned<T>::value,A<T>>::type
operator-(A<T>) {return {};}

int main() {
    A<signed> b;
    -b; // ok

    A<unsigned> a;
    -a; // error
}
#包括
模板
结构A{
};
模板
typename std::enable_if::value,A>::type
运算符-(A){return{};}
int main(){
A b;
-b、 //好的
A A;
-a、 //错误
}
这不会为每个类模板引入成员函数模板


以下是您如何与它成为朋友:

template<class T>
class A {
    int m;

public:
    A(T p) : m(p) {}

    template<class U>
    friend
    typename std::enable_if<!std::is_unsigned<U>::value,A<U>>::type
    operator-(A<U>);
};

template<class T>
typename std::enable_if<!std::is_unsigned<T>::value,A<T>>::type
operator-(A<T> p) {return {p.m};}

int main() {
    A<signed> b(42);
    -b; // ok

    A<unsigned> a(42);
    //-a; // error
}
模板
甲级{
int m;
公众:
A(tp):m(p){}
模板
朋友
typename std::enable_if::value,A>::type
经营者—(A);
};
模板
typename std::enable_if::value,A>::type
运算符-(ap){return{p.m};}
int main(){
A b(42);
-b、 //好的
A(42);
//-a、 //错误
}

不过,您可以(应该)向前声明该函数模板。

使用继承还有很长的路要走:

template <class T>
struct A;

template <class T, bool = std::is_unsigned<T>::value>
struct MinusOperator
{
    A<T> operator-()
    {
        A<T>* thisA = static_cast<A<T>*>(this);
        // use thisA instead of this to get access to members of A<T>
    }
};

template <class T>
struct MinusOperator<T, true> {};

template <class T>
struct A : MinusOperator<T>
{
    friend struct MinusOperator<T>;
};
模板
结构A;
模板
结构运算符
{
操作员-()
{
A*thisA=静态施法(this);
//使用thisA而不是this来访问
}
};
模板
结构运算符{};
模板
结构A:运算符
{
友元结构算子;
};


这里的问题是,当类模板(隐式)实例化时,所有成员函数声明都会实例化。因此,在实例化类模板时,所有成员声明都必须格式良好。嗯,为什么不为所有专门化引入此函数,而是在内部使用
static\u assert
?SFINAE仅在您需要撤退时才需要,但这里可能不需要它。@dyp。。。。事后看来,这是显而易见的,不是吗?对于我的代码来说,这似乎是最好的答案,但可能不是发布的这个问题:(这种方法的唯一问题是,当使用“反射光”(traits/decltype+SFINAE检查)时,“它是谎言”:它总是说“
操作符-
存在”即使无法调用它。@dyp:另外,如果在cpp文件中显式实例化了模板类:
template struct a;
,它也会实例化该函数并产生错误:(尝试在vs2013中用“a b=-b;”进行编译碰撞CL。exe@wonkorealtimeVC++在SFINAE方面有很大的问题。
上面的模板
格式不正确,可能是14.6/8:“如果无法为模板生成有效的专门化,并且该模板未实例化,则该模板格式不正确,无需诊断。”:但是
&A::operator-
或者什么的?有没有办法这么说,这有关系吗?@Yakk我不知道。你是说
之后,A
被实例化,例如,使用
t=int
(非无符号)但是,正如你所说,
操作符-
是一个有效的专门化,只是我们不打算真正使用它,对吗?@iavr是的,但我不确定它是否可以重新调整(语法有效吗?).Evrn如果没有,可能仍然合法。所以,没关系。好吧,这是…简单而直接的O.ointerrenting,一个朋友函数似乎不能阻止它,但有了它,我无法访问私人成员,也无法访问
朋友
it@MooingDuck您可以使用“自由函数”
运算符-
使用函数对象
F
(例如,
运算符-(A){return F()(A);}
),它是
A的
友元
(即
模板结构A{friend F;})
。如果从
MinusOperator
中输入
A
,然后专门化
模板结构MinusOperator
@MooingDuck,我想这会更好。对不起,我无意中读了你的问题。你想对所有未签名类型禁用
操作符-
。但是你对我的解决方案的修复不合适,因为没有模板参数
T
。@MooingDuck我修正了我的答案。默认模板参数只允许在类上使用template@v.oddou从C++11开始就没有了。哦,好吧,然后进行一些编辑来规定这一点,我们很好:)