如何检查静态成员变量模板?

How to check for static member variable template?

本文关键字:变量 静态成员 何检查 检查      更新时间:2023-10-16

我需要定义一个类,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禁用静态模板变量。引用伟大的黎曼的话,"在经过一些短暂的徒劳尝试之后,我暂时搁置了对这个的搜索......">