gpt4 book ai didi

c++ - 将 SFINAE 条件移到最左侧以便于阅读

转载 作者:行者123 更新时间:2023-11-30 02:25:25 25 4
gpt4 key购买 nike

Default template arguments are not considered when compiler judges whether there are some duplicate overload function.

这完全破坏了我的乐趣,而我试图将所有肮脏的东西推到最左边。

这是一个例子。
虽然下面的代码不可编译,但它相对漂亮且易于阅读:-

template<bool enable= a&& b>  typename std::enable_if_t<enable,void> f(){}
template<bool enable= a&&!b> typename std::enable_if_t<enable,void> f(){}
template<bool enable=!a&& b> typename std::enable_if_t<enable,void> f(){}
template<bool enable=!a&&!b> typename std::enable_if_t<enable,void> f(){}
//^ so neat
look like : if(enable){instantiate static f(){}} ... so intuitive!

...与可编译的相比:-

template<bool a1=a,bool b1=b> typename std::enable_if_t< a1&& b1,void> f(){}
template<bool a1=a,bool b1=b> typename std::enable_if_t< a1&&!b1,void> f(){}
template<bool a1=a,bool b1=b> typename std::enable_if_t<!a1&& b1,void> f(){}
template<bool a1=a,bool b1=b> typename std::enable_if_t<!a1&&!b1,void> f(){}
^ two temp "type" ----> scroll -------> ^ deep hidden logic

这似乎是一个微不足道的问题,但它在我的许多文件中反复出现。
这让我很紧张。我开始恐惧地编写 SFINAE。

是否有一些方法可以让它工作并且仍然简洁直观?
这是 coliru demo .

编辑:这是一个更类似于现实世界案例的示例(漂亮但错误的版本):-

template<class X,class A,class B,class C,class D>class Database{
public: static constexpr bool hasC=typename X::hasC;
public: static constexpr bool hasD=typename X::hasD;
/** some complex field (NOT depend on "hasC" and "hasD") */
public: template<bool enable=!hasC&&!hasD>
std::enable_if_t<enable,void> add(A a,B b){
/**some complex */
}
public: template<bool enable=hasC&&!hasD>
std::enable_if_t<enable,void> add(A a,B b,C c){
/**some complex */
}
public: template<bool enable=!hasC&&hasD>
std::enable_if_t<enable,void> add(A a,B b,D d){
/**some complex */
}
public: template<bool enable=hasC&&hasD>
std::enable_if_t<enable,void> add(A a,B b,C c,D d){
/**some complex */
}
};

最佳答案

我认为直到你得到 constexpr if对于 C++17,最清晰的方法是使用标记分派(dispatch):

template<bool a,bool b>
class Test{
public:
void f()
{
fhelp(f_tag<>{});
}
private:
template<bool = a, bool = b>
struct f_tag{};

void fhelp(f_tag<true, true>){}
void fhelp(f_tag<true, false>){}
void fhelp(f_tag<false, true>){}
void fhelp(f_tag<false, false>){}
};

这样我们就可以更明确地知道 ab 的预期值是什么。这很有效,尤其是因为您的条件都是 &&。肉眼也更明显地看出没有两个重载是相同的。

Demo


编辑

C++17 版本会让我们这样写 f():

void f()
{
if constexpr (a && b)
{
// ...
}
if constexpr (a && !b)
{
// ...
}
if constexpr (!a && b)
{
// ...
}
if constexpr (!a && !b)
{
// ...
}
}

事实上,这毕竟可能不是很清晰。就我个人而言,我仍然更喜欢标记派发方式。


编辑2:

关于函数具有不同参数的“真实世界”示例,您可能会开始考虑专门化该类。但是,您仍然可以通过标签分派(dispatch)完成您需要的工作。面向公众的函数需要成为一个可变参数模板,而辅助函数保留它们的真实类型,所以你仍然是安全的:

public: 
template<bool = X::hasC, bool = X::hasD>
struct add_tag{};

template<class... T>
void add(T&&... args)
{
add_help(add_tag<>{}, std::forward<T>(args)...);
}

private:
void add_help(add_tag<false, false>, A a, B b)
{/*..*/}
void add_help(add_tag<true, false>, A a, B b, C c)
{/*..*/}
void add_help(add_tag<false, true>, A a, B b, D d)
{/*..*/}
void add_help(add_tag<true, true>, A a, B b, C c, D d)
{/*..*/}

Demo2

关于c++ - 将 SFINAE 条件移到最左侧以便于阅读,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44158691/

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