假设我有以下代码:
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
的数据类型(与标准函数重载不同)。
答案 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>;