将返回类型专用化为 void 或 const 左值引用

specialize return type to void or const lvalue reference

本文关键字:const 引用 void 返回类型 专用      更新时间:2023-10-16

我正在尝试完成以下任务。

enum class Options : uint8_t {    
optA,
optB,
optC
};
class Test {
public:
static std::string str;
static std::vector<std::string> vec;
template<Options option>
static auto func()
{
if constexpr (option == Options::optA)
{
return str; // want this to deduce to 'const std::string', but only does so if 'const auto' (const std::string& also fine though)
}
else if constexpr (option == Options::optB)
{
return vec; // want this to deduce to 'const std::vector<std::string>&' but only does so if 'const auto&'
}
// want this to deduce to 'void' but only can if 'auto'
}
}

但是,由于注释的原因,它当然不起作用。

我知道我可以...

1(为每个选项专门化类体外的函数,并特意指定返回类型

或 2( 调用函数时显式传入返回类型

但是有没有更干净的解决方案,我需要做的就是将单个Options值传递到模板中,其余的在单个函数体中派生?

const std::string& value = Test::func<Options::optA>();
const std::vector<std::string>& values = Test::func<Options::optB>();
Test::func<Options::optC>();

对于非静态func(),您可以将其标记为const并使用decltype(auto)推导:

template<Options option>
decltype(auto) func() const
{
if constexpr (option == Options::optA)
return (str);
else if constexpr (option == Options::optB)
return (vec);
}

strvec都用括号括起来,以便decltype(auto)推断引用类型。对于optA,它将返回const std::string&,对于optBconst std::vector<std::string>&,否则void

演示 1

对于静态成员

函数和静态成员,您可以编写:

template<Options option>
static decltype(auto) func()
{
if constexpr (option == Options::optA)
return std::as_const(str);
else if constexpr (option == Options::optB)
return std::as_const(vec);
}

演示 2

无需返回const std::string。 您可以只返回一个std::string,调用方可以决定是否希望它成为常量。 如果你对此感到满意,那么你的函数将成为

template<Options option>
static decltype(auto) func()
{
if constexpr (option == Options::optA)
{
return str;
}
else if constexpr (option == Options::optB)
{
return const_cast<const std::vector<std::string>&>(vec);
}
else        //
{           // this bit is not really needed but I like 
return; // being explicit that `void` is what we want to return
//
}           //
}

现在decltype(auto)将推断出Options::optA一个std::stringOptions::optB一个const std::vector<std::string>&Options::optCvoid