C++:在模板化类型 class 中提供一个 class 函数来判断命名成员是否存在于其模板化类型中?
C++: providing a class function in templated class on existence of named member in its templated type?
我正在尝试执行以下操作:模板化的 class 应该提供一些函数,这取决于它被模板化的类型是否包含具有给定名称的成员变量。作为示例,仅当模板化 struct/class 具有名为 "id" 的成员时,才应提供 "printid()" 的伪代码:
#include <iostream>
#include <type_traits>
struct A { int id; };
struct B { };
template<typename T>
class foo
{
T myvar;
public:
#if exists T.id (or the alternative: #if exists myvar.id)
printid() { std::cout << "I have element id."; }
#endif
};
int main(){
foo<A> ok;
ok.printid(); // should compile and execute
foo<B> nok;
nok.printid(); // should not compile
return 0;
}
围绕 SFINAE、traits、std::enable_if 和 Whosebug 进行挖掘,我认为它可以完成……不知何故。但是我不知何故未能将 enable_if 与问题 How to detect whether there is a specific member variable in class?:
中的以下片段结合起来
template<typename T, typename = void>
struct has_id : std::false_type { };
template<typename T>
struct has_id<T, decltype(std::declval<T>().id, void())> : std::true_type { };
感谢任何帮助。
是的,这是可能的。这是一个例子:
template<typename T>
class foo
{
T myvar;
public:
template <class _T = T,
class = typename std::enable_if<
!std::is_function<decltype(_T::id)>::value>
::type>
void printid() { std::cout << "I have element id."; }
};
具体来说,请注意我们如何将 "taking in" T
设置为 _T
以便不对 class 模板参数施加约束(这将使 class 本身成为 un-compileable)。相反,我们正在创建一个新的、独立的模板成员函数,它不会在 T
本身上强制任何东西——它只是 "happens to" 将它用作默认参数。这是关键部分。
我正在尝试执行以下操作:模板化的 class 应该提供一些函数,这取决于它被模板化的类型是否包含具有给定名称的成员变量。作为示例,仅当模板化 struct/class 具有名为 "id" 的成员时,才应提供 "printid()" 的伪代码:
#include <iostream>
#include <type_traits>
struct A { int id; };
struct B { };
template<typename T>
class foo
{
T myvar;
public:
#if exists T.id (or the alternative: #if exists myvar.id)
printid() { std::cout << "I have element id."; }
#endif
};
int main(){
foo<A> ok;
ok.printid(); // should compile and execute
foo<B> nok;
nok.printid(); // should not compile
return 0;
}
围绕 SFINAE、traits、std::enable_if 和 Whosebug 进行挖掘,我认为它可以完成……不知何故。但是我不知何故未能将 enable_if 与问题 How to detect whether there is a specific member variable in class?:
中的以下片段结合起来template<typename T, typename = void>
struct has_id : std::false_type { };
template<typename T>
struct has_id<T, decltype(std::declval<T>().id, void())> : std::true_type { };
感谢任何帮助。
是的,这是可能的。这是一个例子:
template<typename T>
class foo
{
T myvar;
public:
template <class _T = T,
class = typename std::enable_if<
!std::is_function<decltype(_T::id)>::value>
::type>
void printid() { std::cout << "I have element id."; }
};
具体来说,请注意我们如何将 "taking in" T
设置为 _T
以便不对 class 模板参数施加约束(这将使 class 本身成为 un-compileable)。相反,我们正在创建一个新的、独立的模板成员函数,它不会在 T
本身上强制任何东西——它只是 "happens to" 将它用作默认参数。这是关键部分。