gpt4 book ai didi

c++ - 使用 decltype() 和 SFINAE 的错误

转载 作者:太空狗 更新时间:2023-10-29 21:29:44 24 4
gpt4 key购买 nike

为了回答 .. 某处的其他问题,我编写了这段代码。

struct no_type{};
template<typename T> struct has_apply {
static decltype(T().apply<0u>(double())) func( T* ptr );
static no_type func( ... );
static const bool result = !std::is_same<no_type, decltype(func(nullptr))>::value;
};

class A {
public:
template< unsigned n >
void apply( const double& );

};
class B {
};

int main()
{
std::cout << std::boolalpha << has_apply< A >::result << '\n';
std::cout << std::boolalpha << has_apply< B >::result << '\n';
std::cin.get();
return( 0 );
}

现在在我看来,如果 T 提供接受双右值和模板参数文字的非静态成员函数“apply”,结果应该为真,否则为假。但是,在编译时给出的示例实际上无法为 B 类编译 has_apply<B> .在 decltype 语句中替换 T 失败的事实不应该意味着它只是调用另一个 func 吗?这不是 SFINAE 的重点吗?

以有史以来最荒谬、毫无意义的方式解决了问题:

struct no_type{};
template<typename T> struct has_apply {
template<typename U> static decltype(U().apply<0u>(double())) func( U* );
template<typename U> static no_type func( ... );
static const bool result = !std::is_same<no_type, decltype(func<T>(nullptr))>::value;
};

class A {
public:
template< unsigned n >
void apply( const double& );

};
class B {
};

int main()
{
std::cout << std::boolalpha << has_apply< A >::result << '\n';
std::cout << std::boolalpha << has_apply< B >::result << '\n';
std::cin.get();
return( 0 );
}

最佳答案

当函数模板的模板参数替换失败时,SFINAE 适用,而不适用于具有(非模板)函数作为成员的类模板的模板参数,就像您的情况一样。

修复后,您至少应该更改 decltype(T().apply<0u>(double()))decltype(T().template apply<0u>(double()))因为T()表达式是依赖类型。原因是:当编译器第一次看到 T().apply<0u> 时, 它对 T 一无所知然而,它应该如何解析标记 apply<. 之后? apply可能是成员模板,然后是 <将为它启动参数列表。奥托apply可能改为非模板成员(例如数据成员),然后是 <将被解析为“小于”运算符。有一个歧义,编译器现在解决这个问题还为时过早。程序员需要一种消歧机制来告诉编译器什么 apply预计是:模板与否。 .template 来了(或 ->template::template )构造来拯救:如果它存在,编译器知道它应该是一个模板成员,否则如果它不存在,那么编译器知道该成员不应该是模板。

最后,这是我创建的一个示例,它可以正常工作并在 g++ 4.5.0 上使用 -std=c++0x 生成所需的结果。 :

#include <iostream>

template < class T >
decltype( T().template apply< 0u >( double() ) ) f( T &t )
{
return t.template apply< 0u >( 5. );
}

const char *f( ... )
{
return "no apply<>";
}

class A {
public:
template < unsigned >
int apply( double d )
{
return d + 10.;
}
};

class B {};

int main()
{
A a;
std::cout << f( a ) << std::endl;
B b;
std::cout << f( b ) << std::endl;
}

输出是:

15
no apply<>

现在,如果您同时删除 .template从第一个f()定义,则输出变为:

no apply<>
no apply<>

表示class A替换失败因为它没有任何名为 apply非模板成员. SFINAE 在行动!

关于c++ - 使用 decltype() 和 SFINAE 的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4137039/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com