decltype(vector<Type>) doesn't compile

Started by
7 comments, last by Juliean 9 years, 7 months ago

Hello,

I have a chain of classes with a pair of templated set/get methods that require different return semantics based on the type.


float pod = GetAttribute<float>(0);
SomeClass* pObject = GetAttribute<SomeClass>(1);
std::vector<float>& vPOD = GetAttributeArray<float>(2);
const std::vector<SomeClass*>& vObjects= GetAttributeArray<SomeClass>(2);

auto & decltype seemed to do the job:


template<typename Type>
auto Variable::GetValue(void) const -> decltype(returnSemantics<Type>::value)
{
	ACL_ASSERT(m_type == getVariableType<Type>::type);
	ACL_ASSERT(m_isArray == isArray<Type>::value);

	return getObjectData<Type, isPrimitiveType<Type>::value>::GetData(m_pData, m_objectType);
}

returnSemantics is a templated struct that gets specialized for the destired return type:


template<typename Type, bool isPOD = isPrimitiveType<Type>::value>
struct returnSemantics
{
	static Type value = Type();
};

template<typename Type>
struct returnSemantics<Type, true>
{
	static Type value;
};

template<typename Type>
Type returnSemantics<Type, true>::value = Type();

template<typename Type>
struct returnSemantics<Type, false>
{
	static Type* value;
};

template<typename Type>
Type* returnSemantics<Type, false>::value = nullptr;

However, I can't seem to get this to work with the "array"-overload of the method:


template<typename Type>
auto AttributeComponent::GetAttributeArray(unsigned int slot) -> decltype(core::returnSemantics<std::vector<Type>>::value)
{
	return GetAttribute<std::vector<Type>>(slot);
}

When I use this code like in the examples above, I get:


error C2893: Funktionsvorlage 'unknown-type acl::event::AttributeComponent::GetAttributeArray(unsigned int)' konnte nicht spezialisiert werden
1>          Mit den folgenden Vorlagenargumenten:
1>          'Type=int'

which translates to something along the lines of "function template '...' could not be specialized with template arguments 'Type=int'. Why? Is there anything wrong with the decltype-usage?


decltype(core::returnSemantics<std::vector<Type>>::value)

I'm using the "Type" argument to form a vector, and use the vector as template-argument for my returnSemantics-structure... I'm using Visual Studio 2013, does anybode see the issue here?

EDIT: Also fails without the specific overload, even using


std::vector<float>& vTest = GetAttribute<std::vector<float>>(0);

which calls the first posted method fails with the same compilation error...

Advertisement
decltype is very fragile with VS ... not that your problem has anything to do with it, just mentioning to be cautious in relying on it.

Anyway, what you seem to want is:
std::conditional<std::is_pod<SomeType>::value, SomeType, SomeType*>::type
also, might want to typedef it if it is needed often for readability:
typedef typename std::conditional<std::is_pod<SomeType>::value, SomeType, SomeType*>::type NewType;
edit: "typename" is of course not needed if SomeType is not template parameter - kind of wrote it on autopilot.

Thank you for your suggestion,

it appears though that using std::conditional in this case also doesn't work. There appears to be a general problem with using a "typedef" as part of an auto-specializer, or am I doing something wrong here?


template<typename Type>
auto get(void) -> decltype(typename std::conditional<true, Type, Type*>::type)
{
	return 1.0f;
}

int main(void)
{
	auto test = get<float>();

	return 1;
}

This yields me a "error C2893: function template unknown-type get(void) could not be specialized". Putting the std::conditional instead of the auto also doesn't work. Only if I specificy the values of Type and Type* explicitely in the declaration, it compiles & runs. Is there some special syntax I need here?

EDIT: ok, at first I forgot typename, that at least removes the intellisense-error, but compilation still fails. Come to think of it, I still didn't update my visual studio due to my crappy internet - might give it a try, maybe thats some kind of earily-visual-studio error that is also resolved by updating like the last time. If you see anything aside from that, let me know regardless.

Are you using the latest VS toolset? Maybe that could help.


Are you using the latest VS toolset? Maybe that could help.

Yeah, I don't know if you have seen my edit, I always keep forgetting that I'm running a pretty outdated VS on this PC. Its actually still a "preview"-version, don't know how that happens since I didn't install VS2013 before after the release, but oh well... lets see how this turns out after the update. I am actually tempted to try out the November CTP with c++14 support, since this would let me put the function simply as


template<typename Type>
auto Variable::GetValue(void)
{
    ACL_ASSERT(m_type == getVariableType<Type>::type);
    ACL_ASSERT(m_isArray == isArray<Type>::value);

    return getObjectData<Type, isPrimitiveType<Type>::value>::GetData(m_pData, m_objectType);
}

without the decltype(), as getObjectData already returns with the correct semantic... but first things first.

it appears though that using std::conditional in this case also doesn't work. There appears to be a general problem with using a "typedef" as part of an auto-specializer, or am I doing something wrong here?

template<typename Type>
auto get(void) -> decltype(typename std::conditional<true, Type, Type*>::type) { ...

"typename std::conditional<true, Type, Type*>::type" is already a type - what is "decltype" doing there? VS likes to crap its pants when "decltype" contains something outside of the limited set of things it finds edible.

I assume you tried without "decltype" and still got some kind of problems - would be worth copy-pasting here (NOT intellisense output - it is for fast overview, which while extremely useful normally, tends to hide some tiny details).

Also, use "typedef" for divide-and-conquer approach:
template<typename T> struct Test {
    typedef typename std::conditional<true, Type, Type*>::type NewType;
};

Test<something-in-particular>::NewType instantiationCheck;

template<typename Type> Test<Type>::NewType get(void) { ... }
... in case something in your actual templated function is at fault.


"typename std::conditional::type" is already a type - what is "decltype" doing there? VS likes to crap its pants when "decltype" contains something outside of the limited set of things it finds edible.

I assume you tried without "decltype" and still got some kind of problems - would be worth copy-pasting here (NOT intellisense output - it is for fast overview, which while extremely useful normally, tends to hide some tiny details).

Also, use "typedef" for divide-and-conquer approach:

template struct Test {
typedef typename std::conditional::type NewType;
};

Test::NewType instantiationCheck;

template Test::NewType get(void) { ... }
,>,>

Yeah, decltype was definately wrong here. I put it here because I saw it as the only possible syntax for doing so since I got multiple compilation errors when puttin the template-typedef as first argument (copy/pasting it is not so easy because my VS is in german). However, the solution is:


template<typename Type> 
struct Test 
{
    typedef typename std::conditional<true, Type, Type*>::type NewType;
};

template<typename Type> 
typename Test<Type>::NewType get(void) { ... }

I'm pretty sure I tried putting typename with the template ::NewType as return argument before and it failed before the update, but yeah, now its working, thanks.

,>,>

Completely OT, but what does that emote mean? Never seen it before and it is rather difficult to Google for it x_x.

copy/pasting it is not so easy because my VS is in german

Yeah noticed. My grasp of German is still fairly good, besides - the gibberish part between the fairly standard text is where the problem is actually shown.

Btw, OT again, why do you use German for VS? English is not my native language either, but i still strongly prefer all my tools to be in English - easier to Google stuff etc (ie. the knowledge pool in English is a far greater benefit than the un-noteworthy benefit of having some tools in ones native language).

edit: Oh, yeah "template<typename Type> typename Test<Type>::NewType get(void) { ... }" - forgot the second "typename" there. Oh C++, you so silly.


Completely OT, but what does that emote mean? Never seen it before and it is rather difficult to Google for it x_x.

Thats not really an emoticon, its not even supposed to be there. Don't know where it comes from really, maybe some issue with copy/post or the quote-function^^


Btw, OT again, why do you use German for VS? English is not my native language either, but i still strongly prefer all my tools to be in English - easier to Google stuff etc (ie. the knowledge pool in English is a far greater benefit than the un-noteworthy benefit of having some tools in ones native language).

I'm not entirely sure, I also use english on my main PC, I just happended to have a german version here. I quess my reasoning behind this was that I wanted to have a version where I'm fully able to understand all possible menus/options. I don't usually have problems with english, but sometimes I had troubles with the naming of some specific tool-bar menu or compiler setting. Quess that doesn't matter much at this point, might as well install the english language pack.


edit: Oh, yeah "template typename Test::NewType get(void) { ... }" - forgot the second "typename" there. Oh C++, you so silly.

Yeah, thats also why I'm looking forward to the C++14-solution. Kind of curious if the CTP will even work properly this time. The last one for VS2012 did its job, but I had problems with the 2013-one a few weeks ago.

This topic is closed to new replies.

Advertisement