我有一个模板类,如下所示:
template <typename T> constexpr bool is_value_passable_v = is_trivially_copyable_v<T> && sizeof(T) <= sizeof(void*) && !is_polymorphic_v<T>;
template <typename B, typename T> using param_base_t = conditional_t<is_value_passable_v<B>, T, const T&>;
template <typename T> struct param_d
{
using type = param_base_t<T, T>;
};
template <> struct param_d<void>
{
using type = void;
};
template <typename T> using param_t = typename param_d<T>::type;
template <class TIn> class CClass
{
public:
static constexpr bool use_input_v = !is_same_v<typename TIn::input_t, void>;
using input_t = conditional_t<use_input_v, param_t<typename TIn::input_t>, void>;
enable_if_t<use_input_v> Input(input_t i);
};
此代码的目标是为不同的模板参数提供不同的Input
函数。
input_t = int
的模板参数应为void Input(int i)
input_t = std::vector
的模板参数应为void Input(const std::vector& i)
input_t = void
的模板参数应删除Input
函数使用clang进行编译
/usr/bin/../include/c++/v1/type_traits:225:78: error: no type named 'type' in 'std::__1::enable_if<false, void>'; 'enable_if' cannot be used to disable this declaration
template <bool _Bp, class _Tp = void> using enable_if_t = typename enable_if<_Bp, _Tp>::type;
^~~
编辑1: 添加行
后template <typename T> static constexpr bool use_input2_v = use_input_v;
并用
替换函数声明template <typename T = void> enable_if_t<use_input2_v<T>> Input(input_t i)
clang抱怨no matching member function for call to 'Input'
:
note: candidate template ignored: substitution failure [with T = void]: non-type template argument is not a constant expression
template <typename T = void> enable_if_t<use_input2_v<T>> Input(input_t i);
~~~~~~~~~~~~ ^
编辑2: 忘了提一下,这个错误带有模板参数的所有三种变体。
编辑3:
CClass
的示例用例可能是
class CInput0
{
using input_t = int;
};
class CInput1
{
using input_t = std::vector<int>;
};
class CInput2
{
using input_t = void;
};
CClass<CInput0> in0;
CClass<CInput1> in1;
CClass<CInput2> in2;
std::vector<int> i = {1, 2, 3};
in0.Input(3);
in1.Input(i);
//in2.Input() disabled
答案 0 :(得分:1)
为了使SFINAE工作,它需要处理依赖类型,否则没有替换失败。这是一个例子:
template <typename Self = CClass<TIn>>
typename std::enable_if<Self::use_input_v>::type
Input(typename Self::input_t) { }
当成员函数是模板时,编译器会根据模板参数是否有效来有条件地创建它。在您的原始示例中,由于整个类是模板,但方法不是,因此只要实例化类,编译器就会将其视为您的成员函数的错误。使用默认模板参数只是我们需要的技巧。我们想要测试的内容现在被认为是依赖的。
答案 1 :(得分:0)
如果要根据模板参数的属性启用函数,而不进行部分特化,可以使用以下模式:
#include <iostream>
#include <type_traits>
#include <vector>
std::ostream& operator<<(std::ostream& out, std::vector<int>& value);
template <class TIn> class CClass
{
public:
template <class T =TIn, class PARAM= std::enable_if_t<!(std::is_same<void,typename T::input_t>::value) ,typename T::input_t > >
void Input(PARAM i){
std::cout << "Called Input with parameter: "<< i << std::endl;
}
};
struct CInput0{ using input_t = int;};
struct CInput1{ using input_t = std::vector<int>;};
struct CInput2{ using input_t = void;};
CClass<CInput0> in0;
CClass<CInput1> in1;
CClass<CInput2> in2;
std::vector<int> i = {1, 2, 3};
std::ostream& operator<<(std::ostream& out, std::vector<int>& value) {
for (auto& e:value) {
out << e;
}
out << std::endl;
return out;
}
int main() {
in0.Input(3);
in1.Input(i);
//in2.Input() disabled
}
这是您的示例的简化版本,您应该能够适应它。