Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/124.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++ C++;:用于检查表达式是否编译的模板_C++_Templates_Sfinae_Specialization_Partial Specialization - Fatal编程技术网

C++ C++;:用于检查表达式是否编译的模板

C++ C++;:用于检查表达式是否编译的模板,c++,templates,sfinae,specialization,partial-specialization,C++,Templates,Sfinae,Specialization,Partial Specialization,在使用SFINAE编写模板专门化时,您经常会因为一个不存在的小成员或函数而需要编写一个全新的专门化。我想将此选择打包成一个小语句,如orElse 小例子: template<typename T> int get(T& v){ return orElse<v.get(),0>(); } template int get(T&v){ 返回orElse(); } 这可能吗?是的,这或多或少是可能的。它被称为“成员检测器”。有关如何使用宏实现这一点,请参阅本

在使用SFINAE编写模板专门化时,您经常会因为一个不存在的小成员或函数而需要编写一个全新的专门化。我想将此选择打包成一个小语句,如
orElse

小例子:

template<typename T> int get(T& v){
    return orElse<v.get(),0>();
}
template int get(T&v){
返回orElse();
}

这可能吗?

是的,这或多或少是可能的。它被称为“成员检测器”。有关如何使用宏实现这一点,请参阅本wikibooks。实际实现将取决于您使用的是C++11之前的版本还是之后的版本,以及您使用的编译器。

orElse()的意图非常清楚,但是如果存在这样的情况, 它必须是以下之一:

调用列表

orElse(v,&V::get,0)
orElse<V,&V::get>(v,0)
orElse<V,&V::get,0>(v)
template<typename T>
int orElse(T & obj, int(T::pmf*)(), int deflt);

template<typename T, int(T::*)()>
int orElse(T & obj, int deflt);

template<typename T, int(T::*)(), int Default>
int orElse(T & obj);
正如你所理解的,没有这样一件事能产生你想要的效果

对于任何不明白的人, 原因很简单:调用列表中没有函数调用 如果没有像
V::get
这样的成员,则将编译。没法绕过去 事实上,调用的函数可能是 功能模板列表中的功能模板没有任何区别。 如果
V::get
不存在,那么任何提到它的代码都不会编译

然而,你似乎有一个实际的目标,不需要接近 以这种绝望的方式。看起来,对于给定的名称
foo
和给定的类型
R
, 您希望能够只编写一个函数模板:

template<typename T, typename ...Args>
R foo(T && obj, Args &&... args);
可通过以下方式进行试验:

#include <iostream>

using namespace std;

struct A
{
    A(){};
    int get() {
        return 1;
    }
    int get(int i) const  {
        return i + i;
    }
};

struct B
{
    double get() {
        return 2.2;
    }
    double get(double d) {
        return d * d;
    }
};

struct C{};

int main()
{
    A const aconst;
    A a;
    B b;
    C c;
    cout << get(aconst) << endl;    // expect 0
    cout << get(a) << endl;         // expect 1 
    cout << get(b) << endl;         // expect 0
    cout << get(c) << endl;         // expect 0
    cout << get(a,1) << endl;       // expect 2
    cout << get(b,2,2) << endl;     // expect 0
    cout << get(c,3) << endl;       // expect 0
    cout << get(A(),2) << endl;     // expect 4
    cout << get(B(),2,2) << endl;   // expect 0
    cout << get(C(),3) << endl;     // expect 0
    return 0;
}
#包括
使用名称空间std;
结构A
{
A(){};
int get(){
返回1;
}
int get(int i)const{
返回i+i;
}
};
结构B
{
double get(){
回报率2.2;
}
双接(双d){
返回d*d;
}
};
结构C{};
int main()
{
常数;
A A;
B B;
C C;

CUT如果你不标记C++,几乎没人会看这个。你能再指定一点吗?听起来像“代码> STD::条件<…>代码>……唯一的问题,如果存在,非常有用。如果你把一个表达式放进一个必须编译的模板,就显示这个问题。否则编译器会跳过整个模板。所以,如果我写了类似OREST的东西,因为第一个表达式中的任何错误,它就不能考虑第二个表达式(0)。我想用一些技巧来知道这是可能的。而且,你的帖子是一个可能的副本:“表达式编译”和“成员函数存在”。这是一个很好的开始。我只是认为一个通用的解决方案是可能的。@sp2danny啊,是的,我的错误。我想问题是为什么表达式不能正确编译?问题是否可以归结为成员检测?即,如果特定成员存在然后求值表达式,否则一些默认表达式。我想我也会受益于这个问题的详细阐述。非常好的答案,准确地解释了可能性和不可能性。
#include <iostream>

using namespace std;

struct A
{
    A(){};
    int get() {
        return 1;
    }
    int get(int i) const  {
        return i + i;
    }
};

struct B
{
    double get() {
        return 2.2;
    }
    double get(double d) {
        return d * d;
    }
};

struct C{};

int main()
{
    A const aconst;
    A a;
    B b;
    C c;
    cout << get(aconst) << endl;    // expect 0
    cout << get(a) << endl;         // expect 1 
    cout << get(b) << endl;         // expect 0
    cout << get(c) << endl;         // expect 0
    cout << get(a,1) << endl;       // expect 2
    cout << get(b,2,2) << endl;     // expect 0
    cout << get(c,3) << endl;       // expect 0
    cout << get(A(),2) << endl;     // expect 4
    cout << get(B(),2,2) << endl;   // expect 0
    cout << get(C(),3) << endl;     // expect 0
    return 0;
}
std::enable_if_t<
        std::is_same<R,decltype(obj.get(std::forward<Args>(args)...))
    >::value,R>