英文:
failed to separate return object with SIFNE
问题
I want to build a simple array data wrapper. It shows me a data what I suggested views (like double or character).
This function get_type()
simply returns separate objects with enum
tags (I used SIFNE).
So my expectation was, if some pointer (void* tmp
) existed, when I call get_type<CHARACTER>(tmp, size)
then function would return an arrayview<char>
object.
But it isn't, it raises an error:
c2440 'function-style-cast' cannot convert from 'initializer list' to
This is my full code of my test code (I simplified my problem):
#include <iostream>
using namespace std;
enum class test_array_type {
CHARACTER,
DOUBLE
};
template<typename T>
class arrayview {
// yeah, you might think that why this class is needed,
// I removed many member methods.
public:
T* m_data;
const int m_size;
arrayview(T* data, int size) :m_data(data), m_size(size) {};
};
template<test_array_type T>
struct testType {
using type = typename arrayview<double>;
};
template<>
struct testType<test_array_type::CHARACTER> {
using type = typename arrayview<char>;
};
template<test_array_type ty>
testType<ty>::type get_type(void* tmp) {
switch (ty) {
case test_array_type::CHARACTER:
return testType<test_array_type::CHARACTER>::type(tmp, 10);
case test_array_type::DOUBLE:
return testType<test_array_type::DOUBLE>::type(tmp, 10);
}
}
int main()
{
char* tmp = new char[10];
for (int i = 0; i < 10; i++) {
tmp[i] = 'a' + i;
}
tmp[9] = '#include <iostream>
using namespace std;
enum class test_array_type {
CHARACTER,
DOUBLE
};
template<typename T>
class arrayview {
// yeah, you might think that why this class is needed,
// I removed many member methods.
public:
T* m_data;
const int m_size;
arrayview(T* data, int size) :m_data(data), m_size(size) {};
};
template<test_array_type T>
struct testType {
using type = typename arrayview<double>;
};
template<>
struct testType<test_array_type::CHARACTER> {
using type = typename arrayview<char>;
};
template<test_array_type ty>
testType<ty>::type get_type(void* tmp) {
switch (ty) {
case test_array_type::CHARACTER:
return testType<test_array_type::CHARACTER>::type(tmp, 10);
case test_array_type::DOUBLE:
return testType<test_array_type::DOUBLE>::type(tmp, 10);
}
}
int main()
{
char* tmp = new char[10];
for (int i = 0; i < 10; i++) {
tmp[i] = 'a' + i;
}
tmp[9] = '\0';
testType<test_array_type::CHARACTER>::type ttt = get_type< test_array_type::CHARACTER>(reinterpret_cast<void*>(tmp));
testType<test_array_type::CHARACTER>::type(tmp, 10);
std::cout << reinterpret_cast<char*>(ttt.m_data) << std::endl;
return 0;
}
';
testType<test_array_type::CHARACTER>::type ttt = get_type< test_array_type::CHARACTER>(reinterpret_cast<void*>(tmp));
testType<test_array_type::CHARACTER>::type(tmp, 10);
std::cout << reinterpret_cast<char*>(ttt.m_data) << std::endl;
return 0;
}
How can I solve this problem?
If I remove all constructors except the default constructor, then it compiles. But that's not I want to make.
I think I misunderstand how the compiler and template rules and principles work.
英文:
I want to build a simple array data wrapper. It shows me a data what I suggested views (like double or character).
This function get_type()
simply returns separate objects with enum
tags (I used SIFNE).
So my expectation was, if some pointer (void* tmp
) existed, when I call get_type<CHARACTER>(tmp, size)
then function would return an arrayview<char>
object.
But it isn't, it raises an error:
> c2440 ' function-style-cast ' cannot convert from 'initializer list' to
This is my full code of my test code (I simplified my problem):
#include <iostream>
using namespace std;
enum class test_array_type {
CHARACTER,
DOUBLE
};
template<typename T>
class arrayview {
// yeah, you might think that why this class is needed,
// I removed many member methods.
public:
T* m_data;
const int m_size;
arrayview(T* data, int size) :m_data(data), m_size(size) {};
};
template<test_array_type T>
struct testType {
using type = typename arrayview<double>;
};
template<>
struct testType<test_array_type::CHARACTER> {
using type = typename arrayview<char>;
};
template<test_array_type ty>
testType<ty>::type get_type(void* tmp) {
switch (ty) {
case test_array_type::CHARACTER:
return testType<test_array_type::CHARACTER>::type(tmp, 10);
case test_array_type::DOUBLE:
return testType<test_array_type::DOUBLE>::type(tmp, 10);
}
}
int main()
{
char* tmp = new char[10];
for (int i = 0; i < 10; i++) {
tmp[i] = 'a' + i;
}
tmp[9] = '#include <iostream>
using namespace std;
enum class test_array_type {
CHARACTER,
DOUBLE
};
template<typename T>
class arrayview {
// yeah, you might think that why this class is needed,
// I removed many member methods.
public:
T* m_data;
const int m_size;
arrayview(T* data, int size) :m_data(data), m_size(size) {};
};
template<test_array_type T>
struct testType {
using type = typename arrayview<double>;
};
template<>
struct testType<test_array_type::CHARACTER> {
using type = typename arrayview<char>;
};
template<test_array_type ty>
testType<ty>::type get_type(void* tmp) {
switch (ty) {
case test_array_type::CHARACTER:
return testType<test_array_type::CHARACTER>::type(tmp, 10);
case test_array_type::DOUBLE:
return testType<test_array_type::DOUBLE>::type(tmp, 10);
}
}
int main()
{
char* tmp = new char[10];
for (int i = 0; i < 10; i++) {
tmp[i] = 'a' + i;
}
tmp[9] = '\0';
testType<test_array_type::CHARACTER>::type ttt = get_type< test_array_type::CHARACTER>(reinterpret_cast<void*>(tmp));
testType<test_array_type::CHARACTER>::type(tmp, 10);
std::cout << reinterpret_cast<char*>(ttt.m_data) << std::endl;
return 0;
}
';
testType<test_array_type::CHARACTER>::type ttt = get_type< test_array_type::CHARACTER>(reinterpret_cast<void*>(tmp));
testType<test_array_type::CHARACTER>::type(tmp, 10);
std::cout << reinterpret_cast<char*>(ttt.m_data) << std::endl;
return 0;
}
How can I solve this problem?
If I remove all constructors except the default constructor, then it compiles. But that's not I want to make.
I think I misunderstand how the compiler and template rules and principles work.
答案1
得分: 1
SIFNE是什么?你是不是指的是SFINAE(替代失败不是错误)?你的代码中没有SFINAE。
你的get_type()
方法试图基于一个enum
返回两个不相关的类型,但在C++中无法这样做。
而不是使用switch
,你应该使用以下之一:
if constexpr
(C++17及更高版本):
template<test_array_type ty>
auto get_type(void* tmp) {
if constexpr (ty == test_array_type::CHARACTER) {
return testType<test_array_type::CHARACTER>::type{tmp, 10};
} else {
return testType<test_array_type::DOUBLE>::type{tmp, 10};
}
// 或者简单地:
// return testType<ty>::type{tmp, 10};
}
- 模板特化:
template<test_array_type ty>
void get_type(void*) {}
template<>
arrayview<char> get_type<test_array_type::CHARACTER>(void* tmp) {
return arrayview<char>{tmp, 10};
}
template<>
arrayview<double> get_type<test_array_type::DOUBLE>(void* tmp) {
return arrayview<double>{tmp, 10};
}
英文:
What is SIFNE? Did you mean SFINAE (Substitution Failure Is Not An Error)? There is no SFINAE in your code.
Your get_type()
method is trying to return
two unrelated types based on an enum
, but you can't do that in C++.
Instead of using a switch
, you should use either:
if constexpr
(C++17 and later):
template<test_array_type ty>
auto get_type(void* tmp) {
if constexpr (ty == test_array_type::CHARACTER) {
return testType<test_array_type::CHARACTER>::type{tmp, 10};
} else {
return testType<test_array_type::DOUBLE>::type{tmp, 10};
}
// or simply:
// return testType<ty>::type{tmp, 10};
}
template<test_array_type ty>
void get_type(void*) {}
template<>
arrayview<char> get_type<test_array_type::CHARACTER>(void* tmp) {
return arrayview<char>{tmp, 10};
}
template<>
arrayview<double> get_type<test_array_type::DOUBLE>(void* tmp) {
return arrayview<double>{tmp, 10};
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论