如何检查静态成员变量模板?
How to check for static member variable template?
我需要定义一个类,foo
,带有静态成员变量模板,foo::static_variable_template<T>
。仅当T
满足某些要求时,此成员才应存在。例如,当 constexpr 静态函数T::constexpr_static_function()
存在时。否则,foo::static_variable_template<T>
不应该存在。此外,我希望能够通过 SFINAE 在编译时测试foo::static_variable_template<T>
是否存在。
以下是我想做的近似值:
#include <iostream>
struct foo
{
template<class T>
static constexpr int static_variable_template =
T::constexpr_static_function();
// XXX this works but requires a second defaulted template parameter
// template<class T, int = T::constexpr_static_function()>
// static constexpr int static_variable_template =
// T::constexpr_static_function();
};
struct has_constexpr_static_function
{
static constexpr int constexpr_static_function() { return 42; }
};
struct hasnt_constexpr_static_function
{
};
template<class T, class U,
int = T::template static_variable_template<U>>
void test_for_static_variable_template(int)
{
std::cout << "yes it hasn";
}
template<class T, class U>
void test_for_static_variable_template(...)
{
std::cout << "no it hasn'tn";
}
int main()
{
test_for_static_variable_template<foo, has_constexpr_static_function>(0);
test_for_static_variable_template<foo, hasnt_constexpr_static_function>(0);
}
此近似值几乎有效,但前提是foo::static_variable_template
具有第二个默认模板参数。因为第二个参数是一个实现细节,所以我想从foo::static_variable_template
的公共接口中隐藏它。
这在 C++17 中可能吗?
我不确定您的意图是使用0
初始化foo::static_variable_template
是否缺少T::constexpr_static_function()
或者您想完全禁用它。在前者的情况下,这可能是有用的。例如,这个(笨拙的)解决方案有效(if constexpr
需要 C++17 ;请注意,您的变量现在是一个函数):
#include <iostream>
template <typename T>
class has_func
{
typedef char does;
typedef long doesnt;
template <typename C> static does test( decltype(&C::constexpr_static_function) );
template <typename C> static doesnt test(...);
public:
static constexpr bool value()
{
return sizeof(test<T>(0)) == sizeof(char);
}
};
struct foo
{
template<class T>
static constexpr int static_variable_template()
{
if constexpr (has_func<T>::value())
{
return T::constexpr_static_function();
}
return 0;
}
// XXX this works but requires a second defaulted template parameter
// template<class T, int = T::constexpr_static_function()>
// static constexpr int static_variable_template =
// T::constexpr_static_function();
};
struct has_constexpr_static_function
{
static constexpr int constexpr_static_function() { return 42; }
};
struct hasnt_constexpr_static_function
{
};
template<class T, class U>
void test_for_static_variable_template(...)
{
if constexpr (has_func<U>::value())
{
std::cout << "yes it hasn";
}
else
{
std::cout << "no it hasn'tn";
}
}
int main()
{
std::cout << foo::static_variable_template<has_constexpr_static_function>() << "n";
std::cout << foo::static_variable_template<hasnt_constexpr_static_function>() << "n";
/// Original test
test_for_static_variable_template<foo, has_constexpr_static_function>(0);
test_for_static_variable_template<foo, hasnt_constexpr_static_function>(0);
}
指纹
42
0
yes it has
no it hasn't
用clang 5.0.1
测试。
如果要完全禁用foo::static_variable_template
,则可能需要使用std::enable_if
:
#include <iostream>
template <typename T>
class has_func
{
typedef char does;
typedef long doesnt;
template <typename C> static does test( decltype(&C::constexpr_static_function) );
template <typename C> static doesnt test(...);
public:
static constexpr bool value()
{
return sizeof(test<T>(0)) == sizeof(char);
}
};
struct foo
{
template<class T, typename std::enable_if<has_func<T>::value()>::type ...>
static constexpr int static_variable_template()
{
if constexpr (has_func<T>::value())
{
return T::constexpr_static_function();
}
return 0;
}
// XXX this works but requires a second defaulted template parameter
// template<class T, int = T::constexpr_static_function()>
// static constexpr int static_variable_template =
// T::constexpr_static_function();
};
struct has_constexpr_static_function
{
static constexpr int constexpr_static_function() { return 42; }
};
struct hasnt_constexpr_static_function
{
};
template<class T, class U>
void test_for_static_variable_template(...)
{
if constexpr (has_func<U>::value())
{
std::cout << "yes it hasn";
}
else
{
std::cout << "no it hasn'tn";
}
}
int main()
{
std::cout << foo::static_variable_template<has_constexpr_static_function>() << "n";
// We can't print this because it doesn't exist.
// std::cout << foo::static_variable_template<hasnt_constexpr_static_function>() << "n";
/// Original test
test_for_static_variable_template<foo, has_constexpr_static_function>(0);
test_for_static_variable_template<foo, hasnt_constexpr_static_function>(0);
}
按照这种思路,我不确定您是否可以使用std::enable_if
禁用静态模板变量。引用伟大的黎曼的话,"在经过一些短暂的徒劳尝试之后,我暂时搁置了对这个的搜索......">
- C++:是否可以使用非静态成员变量模板?
- 如何在复杂继承中访问静态成员变量
- 静态成员变量不会由 gettext 转换
- 未使用的C++未优化的静态成员函数/变量
- 为什么我不能像这样在静态成员函数中调用静态成员变量?
- C++ lambda - 捕获静态成员变量
- 多线程处理中的静态成员变量
- 纯标头库中静态成员变量的正确设置器和 getter
- 如何从具有专用化的类模板定义静态成员变量?
- 从静态成员函数访问私有非静态类变量 - C++
- 静态变量与静态成员
- 为什么可以在没有实例变量的情况下访问静态回调方法中的静态成员变量?
- 声明和定义类静态成员变量不会导致多重声明,这是为什么?
- 为什么不允许静态成员变量的初始化在类中,而允许静态静态成员的初始化
- 类中的静态成员变量和C++中的全局变量有什么区别?
- 获取 constexpr 全局变量(不是静态成员)的链接器符号
- C++ 静态成员变量 - 文件之间的访问
- 将非静态成员函数C 的使用无效,而将成员功能作为函数变量
- 如何在运行时使用静态成员函数初始化静态成员变量
- 如何在类静态成员中引用静态变量?