-1

Visual Studio 2013 is a bit weird on language array that in global function it's allowed to initialize one as char result[100] = { 0 };, but not if it's a class's member -- referring to Workaround for error C2536: cannot specify explicit initializer for arrays in Visual Studio 2013, for int m_array[3]; inside class A, A() :m_array{ 0, 1, 2 } {} fails with Error C2536: "'A::A::m_array' : cannot specify explicit initializer for arrays".

In the same post a work-around is suggested, using std::array<int, 3> m_array; instead and initilzie with A() : m_array ({ 0, 1, 2 }) {} , IDE red underlined "0" hinting "Error: braces cannot be omitted for this subobject initializer." but can compile.

Even better, one comments suggested use an extra pair of braces A() : m_array ({ { 0, 1, 2 } }) {} , and now all smooth!

To pass a std::array to a function requiring a char * parameter, std::array over c style array suggest use my_array.data() where my_array is a std::array.

Now I met a problem with _spitpath_s:

The traditional char * style compiles _splitpath_s(fullpathfilename, drive, dir, name, ext) where the parameters are all char arrays; but using std::array will trigger error C2660:

class B2
{
public:
    const int MAX_LEN = 200;
    std::array<char, 200> drive, dir, name, ext;
    B2() :drive({ { 0 } }), dir({ { 0 } }), name({ { 0 } }), ext({ { 0 } }) {}
    void split(const char * fullpathfilename)   {
        _splitpath_s(fullpathfilename, drive.data(), dir.data(), name.data(), ext.data()); //error C2660: '_splitpath_s' : function does not take 5 arguments
    }
};

.

Why _splitpath_s fails here? This is an old C style function, defined in stdlib.h, if there's a work-around in C++, also acceptable.

Community
  • 1
  • 1
athos
  • 6,120
  • 5
  • 51
  • 95

1 Answers1

2

The 5 parameter version of _splitpath_s is a template function, expecting a character pointer for the input path, and C-style character arrays for the other 4. Since you are passing in C++ array objects, the template is not generated and, due to SFINAE it is not available so there is no function that takes 5 parameters.

To use it you'll have to use the 9 parameter version, where you pass in the input addresses and buffer sizes.

1201ProgramAlarm
  • 32,384
  • 7
  • 42
  • 56
  • 1
    But `dir`, `name`, and `ext` also need `.data` on them, then (since that returns a `char *`) you'll need to pass in the lengths. – 1201ProgramAlarm Oct 19 '16 at 00:33
  • you are right, I can use the 9 parameter version. but one more question, how could C++ function delcaration differentiate `char array[200]` from `char *`? I thought during the call there's an automatic "decay" from `char` array to `char` pointer? – athos Oct 19 '16 at 00:39
  • 2
    An array decays to a pointer when passed to a function, but in a template instantiation the compiler treats them differently. In this case it uses the known compile time array size to fill in the appropriate value to then call the 9 parameter version. – 1201ProgramAlarm Oct 19 '16 at 00:43
  • 1
    @athos: It's actually because you pass by reference. You can do it without templates — `void foo(const char (&array)[42]) {} const char array[42] = {}; int main() { foo(array); }` will work just fine — it's just that, for general-purpose use, you'd need to manually write an overload for each combination of array dimensions that you want to use! – Lightness Races in Orbit Oct 19 '16 at 08:15