重载多个功能的简写

时间:2018-11-21 05:56:52

标签: c++ overloading

假设我有以下代码:

bool isString(char* arg) { return true; }
bool isString(const char* arg) { return true; }
bool isString(std::string arg) { return true; }

// Any other type...
template <typename type> bool isString(type arg) { return false; }

问题是,C ++是否允许任何可行的方式将下面的语法缩短为类似于下面的概念(语法简写/糖):

// Could be `char*`, `const char*` or `std::string` here.
bool isString([char*, const char*, std::string] arg) { return true; }

// Any other type...
template <typename type> bool isString(type arg) { return false; }

此处提供的示例不一定用于检测字符串,而是用于解释多行代码专用于重载函数的问题。

想象一下,如果我必须测试100种以上的数据类型是否有效,我会很快想要一种较短的编码方式,而不是键入所有100个重载函数

当然,此语法简写的缺点是无法区分arg的数据类型(与标准函数重载不同)。

4 个答案:

答案 0 :(得分:5)

最好的方法可能是从定义一个识别您的类型的特征开始:

// Concepts for the Array I have tried but not succeeded.
template <size_t length, typename type>
const unsigned int len(type arg[static length]) { return length; }

template <size_t length, typename type>
const unsigned int len(type(&)[length]) { return length; }

// This works for Arrays & Pointers
// but should be less prioritized over the function that detects the Array
template <typename type> const unsigned int len(type* arg) { return sizeof(*arg); }

然后,您可以做各种事情。例如,在您的帖子中实现功能就变成了

template<typename> struct is_string : std::false_type{};

template<> struct is_string<char*>       : std::true_type{};
template<> struct is_string<char const*> : std::true_type{};
template<> struct is_string<std::string> : std::true_type{};

或者,如果您想控制重载解析,并且在参数不是我们所查看的字符串时,从重载集合中删除函数:

template<typename T> constexpr bool isString(T) { return is_string<T>::value; }

<type_traits>标头中已经提供了一些预定义的特征和实用程序。

答案 1 :(得分:2)

力量

#include <type_traits>
#include <string>

template<typename T>
bool is_string(T)
{
    return std::is_constructible<std::string, T>::value;
}

足够吗?

答案 2 :(得分:1)

您可以直接这样做:

template <typename T>
constexpr bool isString()
{
    return std::is_same<T, const char*>::value
        || std::is_same<T, char*>::value
        || std::is_same<T, std::string>::value;
}

然后,如果必须设置过载,则可以使用SFINAE:

template <typename T>
std::enable_if_t<isString<T>()> foo(/**/) { /*..*/}

template <typename T>
std::enable_if_t<!isString<T>()> foo(/**/) { /*..*/}

if constexpr(c ++ 17):

template <typename T>
void foo(/**/)
{
    if constexpr (isString<T>()) {
        /*..*/
    } else {
        /*..*/
    }
}

答案 3 :(得分:1)

这里不需要函数,因为参数的值总是被忽略。 (常量)变量模板就足够了。

#include <string>
#include <iostream>
template <class> const bool is_string = false;
template<> const bool is_string<const char*> = true;
template<> const bool is_string<std::string> = true;

int main() {
   const char* z;
   std::string p;
   int q;

   std::cout << is_string<decltype(z)> << "\n"; 
   std::cout << is_string<decltype(p)> << "\n";
   std::cout << is_string<decltype(q)> << "\n";
}

如果需要功能接口,则提供它很简单

 template<class T>
 constexpr bool is_string_f(const T&) {
     return is_string<T>;
 }

好吧,您说的这些专业都太长了,我们可以缩短它们吗?是的,我们可以。

#include <type_traits>
template<class X, class ... args>
const bool type_is_one_of = (false || ... || std::is_same<X, args>::value);
template <class T> 
bool is_string = type_is_one_of<T, char*, const char*, std::string>;

Live example on ideone